diff --git a/lib/ClassicUi/html/application.js b/lib/ClassicUi/html/application.js deleted file mode 100644 index 62885a3d..00000000 --- a/lib/ClassicUi/html/application.js +++ /dev/null @@ -1,935 +0,0 @@ -var nextVersion; -var im, em; -var ds = 0; -var currency = ""; -var swatt = false; - -// Price plot -var pp; -var pa; -var po = { - title: 'Future energy price', - titleTextStyle: { - fontSize: 14 - }, - backgroundColor: { fill:'transparent' }, - bar: { groupWidth: '90%' }, - legend: { position: 'none' }, - vAxis: { - viewWindowMode: 'maximized' - }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, -}; -var pl = null; // Last price -var tl = null; // Last temperature - -// Day plot -var ep; -var ea; -var eo = { - title: 'Energy use last 24 hours', - titleTextStyle: { - fontSize: 14 - }, - colors: ['#6f42c1', '#6f42c1'], - backgroundColor: { fill:'transparent' }, - bar: { groupWidth: '90%' }, - legend: { position: 'none' }, - vAxis: { - title: 'kWh', - viewWindowMode: 'maximized' - }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, - isStacked: true -}; - -// Month plot -var mp; -var ma; -var mo = { - title: 'Energy use last month', - titleTextStyle: { - fontSize: 14 - }, - colors: ['#6f42c1', '#6f42c1'], - backgroundColor: { fill:'transparent' }, - bar: { groupWidth: '90%' }, - legend: { position: 'none' }, - vAxis: { - title: 'kWh', - viewWindowMode: 'maximized' - }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, - isStacked: true -}; - -// Voltage plot -var vp; -var va; -var vo = { - title: 'Phase voltage', - titleTextStyle: { - fontSize: 14 - }, - backgroundColor: { fill:'transparent' }, - bar: { groupWidth: '90%' }, - vAxis: { - minValue: 200, - maxValue: 260, - ticks: [ - { v: 207, f: '-10%'}, - { v: 230, f: '230V'}, - { v: 253, f: '+10%'} - ] - }, - legend: { position: 'none' }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, -}; - -// Amperage plot -var ap; -var aa; -var ao = { - title: 'Phase current', - titleTextStyle: { - fontSize: 14 - }, - backgroundColor: { fill:'transparent' }, - bar: { groupWidth: '90%' }, - vAxis: { - minValue: 0, - maxValue: 100, - ticks: [ - { v: 25, f: '25%'}, - { v: 50, f: '50%'}, - { v: 75, f: '75%'}, - { v: 100, f: '100%'} - ] - }, - legend: { position: 'none' }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, -}; - -// Import plot -var ip; -var ia; -var io = { - legend: 'none', - backgroundColor: { - fill:'transparent', - stroke: 'transparent' - }, - pieHole: 0.6, - pieSliceText: 'none', - pieStartAngle: 216, - pieSliceBorderColor: 'transparent', - slices: { - 0: { color: 'green' }, - 1: { color: '#eee' }, - 2: { color: 'transparent' } - }, - legend: { position: 'none' }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, - chartArea: { - left: 0, - top: 0, - width: '100%', - height: '100%', - backgroundColor: 'transparent' - } -}; - -// Export plot -var xp; -var xa; -var xo = { - legend: 'none', - backgroundColor: { - fill:'transparent', - stroke: 'transparent' - }, - pieHole: 0.6, - pieSliceText: 'none', - pieStartAngle: 216, - pieSliceBorderColor: 'transparent', - slices: { - 0: { color: 'green' }, - 1: { color: '#eee' }, - 2: { color: 'transparent' } - }, - legend: { position: 'none' }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, - chartArea: { - left: 0, - top: 0, - width: '100%', - height: '100%', - backgroundColor: 'transparent' - } -}; - -// Temperature plot -var td = false; // Disable temperature -var tp; -var ta; -var to = { - title: 'Temperature sensors', - titleTextStyle: { - fontSize: 14 - }, - backgroundColor: { fill:'transparent' }, - bar: { groupWidth: '90%' }, - legend: { position: 'none' }, - vAxis: { - title: '°C', - viewWindowMode: 'maximized' - }, - tooltip: { trigger: 'none'}, - enableInteractivity: false, -}; - -$(function() { - var meters = $('.plot1'); - - if(meters.length > 0) { - // Chart - google.charts.load('current', {'packages':['corechart']}); - google.charts.setOnLoadCallback(setupChart); - } - - // For mqtt - $('#m').on('change', function() { - var inputs = $('.mc'); - inputs.prop('disabled', !$(this).is(':checked')); - }); - - $('#f').on('change', function() { - var val = parseInt($(this).val()); - if(val == 3) { - $('.f3-s').show(); - } else { - $('.f3-s').hide(); - } - }); - - $('#s').on('change', function() { - var port = $('#p'); - if($(this).is(':checked')) { - if(port.val() == 1883) { - port.val(8883); - } - } else { - if(port.val() == 8883) { - port.val(1883); - } - } - }); - - $('#m').trigger('change'); - $('#f').trigger('change'); - - // For wifi - $('#st').on('change', function() { - if($(this).is(':checked')) { - $('.sip').prop('disabled', false); - } else { - $('.sip').prop('disabled', true); - } - }); - $('#st').trigger('change'); - - // For web - $('#as').on('change', function() { - var inputs = $('.ac'); - inputs.prop('disabled', $(this).val() == 0); - }); - - $('#as').trigger('change'); - - // For file upload - $('#fileUploadField').on('change',function(){ - var fileName = $(this).val(); - $(this).next('.custom-file-label').html(fileName); - }) - $('.upload-form').on('submit', function(i, form) { - $('#loading-indicator').show(); - }); - - // For NTP - $('#n').on('change', function() { - var inputs = $('.nc'); - inputs.prop('disabled', !$(this).is(':checked')); - }); - $('#n').trigger('change'); - - $('.ipo,.epo').on('click', function() { - swatt = !swatt; - $('.ipo,.epo').html('wait'); - }); - - // Navbar - switch(window.location.pathname) { - case '/temperature': - $('#temp-link').addClass('active'); - break; - case '/price': - $('#price-link').addClass('active'); - break; - case '/meter': - case '/wifi': - case '/mqtt': - case '/mqtt-ca': - case '/mqtt-cert': - case '/mqtt-key': - case '/domoticz': - case '/web': - case '/ntp': - case '/entsoe': - $('#config-link').addClass('active'); - break; - case '/gpio': - case '/debugging': - case '/configfile': - case '/firmware': - $('#firmware-warn').show(); - case '/reset': - $('#system-link').addClass('active'); - break; - } - - // Check for software upgrade - var swv = $('#swVersion'); - var fwl = $('#fwLink'); - if((meters.length > 0 || fwl.length > 0) && swv.length == 1) { - var v = swv.text().substring(1).split('.'); - var v_major = parseInt(v[0]); - var v_minor = parseInt(v[1]); - var v_patch = parseInt(v[2]); - $.ajax({ - url: swv.data('url'), - dataType: 'json' - }).done(function(releases) { - var isnew = false; - if(/^v\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(swv.text()) && fwl.length == 0) { - releases.reverse(); - var next_patch; - var next_minor; - var next_major; - $.each(releases, function(i, release) { - var ver2 = release.tag_name; - var v2 = ver2.substring(1).split('.'); - var v2_major = parseInt(v2[0]); - var v2_minor = parseInt(v2[1]); - var v2_patch = parseInt(v2[2]); - - if(v2_major == v_major) { - if(v2_minor == v_minor) { - if(v2_patch > v_patch) { - next_patch = release; - } - } else if(v2_minor == v_minor+1) { - next_minor = release; - } - } else if(v2_major == v_major+1) { - if(next_major) { - var mv = next_major.tag_name.substring(1).split('.'); - var mv_major = parseInt(mv[0]); - var mv_minor = parseInt(mv[1]); - var mv_patch = parseInt(mv[2]); - if(v2_minor == mv_minor) { - next_major = release; - } - } else { - next_major = release; - } - } - }); - if(next_minor) { - nextVersion = next_minor; - isnew = true; - } else if(next_major) { - nextVersion = next_major; - isnew = true; - } else if(next_patch) { - nextVersion = next_patch; - isnew = true; - } - } else { - nextVersion = releases[0]; - } - if(nextVersion) { - if(fwl.length > 0) { - var chipset = fwl.data('chipset').toLowerCase(); - $.each(releases, function(i, release) { - if(release.tag_name == nextVersion.tag_name) { - $.each(release.assets, function(i, asset) { - if(asset.name.includes(chipset) && !asset.name.includes("partitions")) { - fwl.prop('href', asset.browser_download_url); - $('#fwDownload').show(); - return false; - } - }); - } - }); - }; - if(isnew) { - $('#newVersionTag').text(nextVersion.tag_name); - $('#newVersionUrl').prop('href', nextVersion.html_url); - $('#newVersion').removeClass('d-none'); - } - } - }); - } - - // Temperature - var tt = $('#temp-template'); - if(tt.length > 0) { - setTimeout(loadTempSensors, 500); - } -}); - -var resizeTO; -$( window ).resize(function() { - if(resizeTO) clearTimeout(resizeTO); - resizeTO = setTimeout(function() { - $(this).trigger('resizeEnd'); - }, 250); -}); - -$(window).on('resizeEnd', function() { - redraw(); -}); - -var zeropad = function(num) { - num = num.toString(); - while (num.length < 2) num = "0" + num; - return num; -} - -var setupChart = function() { - pp = new google.visualization.ColumnChart(document.getElementById('pp')); - ep = new google.visualization.ColumnChart(document.getElementById('ep')); - mp = new google.visualization.ColumnChart(document.getElementById('mp')); - vp = new google.visualization.ColumnChart(document.getElementById('vp')); - ap = new google.visualization.ColumnChart(document.getElementById('ap')); - ip = new google.visualization.PieChart(document.getElementById('ip')); - xp = new google.visualization.PieChart(document.getElementById('xp')); - tp = new google.visualization.ColumnChart(document.getElementById('tp')); - fetch(); - drawDay(); - drawMonth(); -}; - -var redraw = function() { - if(pl != null) { - pp.draw(pa, po); - } - ep.draw(ea, eo); - mp.draw(ma, mo); - vp.draw(va, vo); - ap.draw(aa, ao); - ip.draw(ia, io); - xp.draw(xa, xo); - tp.draw(ta, to); - if(tl != null) { - tp.draw(ta, to); - } -}; - -var drawPrices = function() { - $('#ppc').show(); - $.ajax({ - url: '/energyprice.json', - timeout: 30000, - dataType: 'json', - }).done(function(json) { - currency = json.currency; - data = [['Hour',json.currency + '/kWh', { role: 'style' }, { role: 'annotation' }]]; - var r = 1; - var hour = moment.utc().hours(); - var offset = moment().utcOffset()/60; - var min = 0; - var h = 0; - var d = json["20"] == null ? 2 : 1; - for(var i = hour; i<24; i++) { - var val = json[zeropad(h++)]; - if(val == null) break; - data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val == null ? "" : val.toFixed(d)]; - Math.min(0, val); - }; - for(var i = 0; i < 24; i++) { - var val = json[zeropad(h++)]; - if(val == null) break; - data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val == null ? "" : val.toFixed(d)]; - Math.min(0, val); - }; - pa = google.visualization.arrayToDataTable(data); - po.vAxis.title = json.currency; - if(min == 0) - po.vAxis.minValue = 0; - pp.draw(pa, po); - }); -} - -var drawDay = function() { - $.ajax({ - url: '/dayplot.json', - timeout: 30000, - dataType: 'json', - }).done(function(json) { - data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }, { role: 'annotation' }]]; - var r = 1; - var hour = moment.utc().hours(); - var offset = moment().utcOffset()/60; - var min = 0; - for(var i = hour; i<24; i++) { - var imp = json["i"+zeropad(i)]; - var exp = json["e"+zeropad(i)]; - data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(1)]; - min = Math.min(0, -exp); - }; - for(var i = 0; i < hour; i++) { - var imp = json["i"+zeropad(i)]; - var exp = json["e"+zeropad(i)]; - data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(1)]; - min = Math.min(0, -exp); - }; - ea = google.visualization.arrayToDataTable(data); - if(min == 0) - eo.vAxis.minValue = 0; - - ep.draw(ea, eo); - - setTimeout(drawDay, (61-moment().minute())*60000); - }); -}; - -var drawMonth = function() { - $.ajax({ - url: '/monthplot.json', - timeout: 30000, - dataType: 'json', - }).done(function(json) { - data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }, { role: 'annotation' }]]; - var r = 1; - var day = moment().date(); - var eom = moment().subtract(1, 'months').endOf('month').date(); - var min = 0; - for(var i = day; i<=eom; i++) { - var imp = json["i"+zeropad(i)]; - var exp = json["e"+zeropad(i)]; - data[r++] = [zeropad(i), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(0)]; - min = Math.min(0, -exp); - } - for(var i = 1; i < day; i++) { - var imp = json["i"+zeropad(i)]; - var exp = json["e"+zeropad(i)]; - data[r++] = [zeropad(i), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(0)]; - min = Math.min(0, -exp); - } - ma = google.visualization.arrayToDataTable(data); - if(min == 0) - mo.vAxis.minValue = 0; - mp.draw(ma, mo); - - setTimeout(drawMonth, (24-moment().hour())*60000); - }); -}; - -var drawTemperature = function() { - if(td) return; - - $.ajax({ - url: '/temperature.json', - timeout: 30000, - dataType: 'json', - }).done(function(json) { - if(json.c > 1) { - $('#tpc').show(); - - var r = 1; - var min = 0; - data = [['Sensor','°C', { role: 'style' }, { role: 'annotation' }]]; - $.each(json.s, function(i, o) { - var name = o.n ? o.n : o.a; - data[r++] = [name, o.v, "color: #6f42c1;opacity: 0.9;", o.v.toFixed(1)]; - Math.min(0, o.v); - }); - if(min == 0) - to.vAxis.minValue = 0; - ta = google.visualization.arrayToDataTable(data); - ta.sort("Sensor"); - tp.draw(ta, to); - td = false; - } else { - td = true; - } - }); -}; - -var setStatus = function(id, sid) { - var item = $('#'+id); - item.removeClass('d-none'); - item.removeClass (function (index, className) { - return (className.match (/(^|\s)badge-\S+/g) || []).join(' '); - }); - var status; - if(sid == 0) { - status = "secondary"; - } else if(sid == 1) { - status = "success"; - } else if(sid == 2) { - status = "warning"; - } else { - status = "danger"; - } - item.addClass('badge badge-' + status); -}; - -var voltcol = function(pct) { - if(pct > 85) return '#d90000'; - else if(pct > 75) return'#e32100'; - else if(pct > 70) return '#ffb800'; - else if(pct > 65) return '#dcd800'; - else if(pct > 35) return '#32d900'; - else if(pct > 25) return '#dcd800'; - else if(pct > 20) return '#ffb800'; - else if(pct > 15) return'#e32100'; - else return '#d90000'; -}; - -var ampcol = function(pct) { - if(pct > 90) return '#d90000'; - else if(pct > 85) return'#e32100'; - else if(pct > 80) return '#ffb800'; - else if(pct > 75) return '#dcd800'; - else return '#32d900'; -}; - -var retrycount = 0; -var interval = 5000; -var fetch = function() { - $.ajax({ - url: '/data.json', - timeout: 10000, - dataType: 'json', - }).done(function(json) { - retrycount = 0; - - for(var id in json) { - var str = json[id]; - if(typeof str === "object") { - continue; - } - if(isNaN(str)) { - $('.j'+id).html(str); - } else { - var num = parseFloat(str); - $('.j'+id).html(num.toFixed(num < 0 ? 0 : num < 10 ? 2 : 1)); - } - $('.r'+id).show(); - } - - if(window.moment) { - $('.ju').html(moment.duration(parseInt(json.u), 'seconds').humanize()); - } - - ds = parseInt(json.ds); - - var kib = parseInt(json.m)/1000; - $('.jm').html(kib.toFixed(1)); - if(kib > 32) { - $('.ssl-capable').removeClass('d-none'); - } - - setStatus("esp", json.em); - setStatus("han", json.hm); - setStatus("wifi", json.wm); - setStatus("mqtt", json.mm); - - - if(ip) { - var v = parseInt(json.i); - var pct = Math.min((v*100)/parseInt(json.im), 100); - var append = "W"; - if(v > 1000 && !swatt) { - v = (v/1000).toFixed(1); - append = "kW"; - } - $('.ipo').html(v); - $('.ipoa').html(append); - var arr = [ - ['Slice', 'Value'], - ['', (pct*2.88)], - ['', ((100-pct)*2.88)], - ['', 72], - ]; - io.slices[0].color = ampcol(pct); - ia = google.visualization.arrayToDataTable(arr); - ip.draw(ia, io); - } - - var om = parseInt(json.om); - - if(om > 0) { - $('.rex').show(); - $('.rim').hide(); - if(xp) { - var v = parseInt(json.e); - var pct = Math.min((v*100)/(om*1000), 100); - var append = "W"; - if(v > 1000 && !swatt) { - v = (v/1000).toFixed(1); - append = "kW"; - } - $('.epo').html(v); - $('.epoa').html(append); - var arr = [ - ['Slice', 'Value'], - ['', (pct*2.88)], - ['', ((100-pct)*2.88)], - ['', 72], - ]; - xo.slices[0].color = ampcol(pct); - xa = google.visualization.arrayToDataTable(arr); - xp.draw(xa, xo); - } - } else { - $('.rex').hide(); - $('.rim').show(); - } - - if(vp) { - switch(ds) { - case 1: - vo.title = 'Voltage between'; - break; - case 2: - vo.title = 'Phase voltage'; - break; - } - var c = 0; - var t = 0; - var r = 1; - var arr = [['Phase', 'Voltage', { role: 'style' }, { role: 'annotation' }]]; - if(json.u1) { - var u1 = parseFloat(json.u1); - t += u1; - c++; - var pct = Math.min(Math.max(parseFloat(json.u1)-195.5, 1)*100/69, 100); - arr[r++] = [ds == 1 ? 'L1-L2' : 'L1', u1, "color: " + voltcol(pct) + ";opacity: 0.9;", u1 + "V"]; - } - if(json.u2) { - var u2 = parseFloat(json.u2); - t += u2; - c++; - var pct = Math.min(Math.max(parseFloat(json.u2)-195.5, 1)*100/69, 100); - arr[r++] = [ds == 1 ? 'L1-L3' : 'L2', u2, "color: " + voltcol(pct) + ";opacity: 0.9;", u2 + "V"]; - } - if(json.u3) { - var u3 = parseFloat(json.u3); - t += u3; - c++; - var pct = Math.min(Math.max(parseFloat(json.u3)-195.5, 1)*100/69, 100); - arr[r++] = [ds == 1 ? 'L2-L3' : 'L3', u3, "color: " + voltcol(pct) + ";opacity: 0.9;", u3 + "V"]; - } - v = t/c; - if(v > 0) { - va = google.visualization.arrayToDataTable(arr); - vp.draw(va, vo); - } - } - - if(ap && json.mf) { - switch(ds) { - case 1: - ao.title = 'Line current'; - break; - case 2: - ao.title = 'Phase current'; - break; - } - var dA = false; - var r = 1; - var arr = [['Phase', 'Amperage', { role: 'style' }, { role: 'annotation' }]]; - if(json.i1 || json.u1) { - var i1 = parseFloat(json.i1); - dA = true; - var pct = Math.min((parseFloat(json.i1)/parseInt(json.mf))*100, 100); - arr[r++] = ['L1', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i1 + "A"]; - } - if(json.i2 || json.u2) { - var i2 = parseFloat(json.i2); - dA = true; - var pct = Math.min((parseFloat(json.i2)/parseInt(json.mf))*100, 100); - arr[r++] = ['L2', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i2 + "A"]; - } - if(json.i3 || json.u3) { - var i3 = parseFloat(json.i3); - dA = true; - var pct = Math.min((parseFloat(json.i3)/parseInt(json.mf))*100, 100); - arr[r++] = ['L3', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i3 + "A"]; - } - if(dA) { - aa = google.visualization.arrayToDataTable(arr); - ap.draw(aa, ao); - } - } - - if(json.ea) { - $('#each').html(json.ea.h.u.toFixed(2)); - $('#eachc').html(json.ea.h.c.toFixed(2)); - $('#eacd').html(json.ea.d.u.toFixed(1)); - $('#eacdc').html(json.ea.d.c.toFixed(1)); - $('#eacm').html(json.ea.m.u.toFixed(0)); - $('#eacmc').html(json.ea.m.c.toFixed(0)); - $('#eax').html(json.ea.x.toFixed(1)); - $('#eat').html(json.ea.t.toFixed(0)); - $('.cr').html(currency); - if(currency) { - $('.sp').show(); - } - if(om > 0) { - $('.se').removeClass('d-none'); - $('#eache').html(json.ea.h.p.toFixed(2)); - $('#eacde').html(json.ea.d.p.toFixed(1)); - $('#eacme').html(json.ea.m.p.toFixed(0)); - } - } - - if(json.me) { - $('.me').addClass('d-none'); - $('.me'+json.me).removeClass('d-none'); - $('#ml').html(json.me); - } - - var temp = parseFloat(json.t); - if(temp == -127.0) { - $('.jt').html("N/A"); - $('.rt').hide(); - } else { - $('.rt').show(); - if(tl != temp) { - drawTemperature(); - } - tl = temp; - } - - var vcc = parseFloat(json.v); - if(vcc > 0.0) { - $('.rv').show(); - } else { - $('.rv').hide(); - } - - var unixtime = moment().unix(); - var ts = parseInt(json.c); - if(Math.abs(unixtime-ts) < 300) { - $('.jc').html(moment(ts * 1000).format('DD. MMM HH:mm')); - $('.jc').removeClass('text-danger'); - } else { - $('.jc').html(moment(ts * 1000).format('DD.MM.YYYY HH:mm')); - $('.jc').addClass('text-danger'); - } - - var mt = parseInt(json.mt); - switch(mt) { - case 1: - $('.jmt').html("Aidon"); - break; - case 2: - $('.jmt').html("Kaifa"); - break; - case 3: - $('.jmt').html("Kamstrup"); - break; - case 8: - $('.jmt').html("Iskra"); - break; - case 9: - $('.jmt').html("Landis+Gyr"); - break; - case 10: - $('.jmt').html("Sagemcom"); - break; - default: - $('.jmt').html(""); - } - - setTimeout(fetch, interval); - - var price = parseFloat(json.p); - if(price && price != pl) { - pl = price; - drawPrices(); - } - }).fail(function(x, text, error) { - if(retrycount > 2) { - console.log("Failed request"); - console.log(text); - console.log(error); - setTimeout(fetch, interval*4); - - setStatus("mqtt", 0); - setStatus("wifi", 0); - setStatus("han", 0); - setStatus("esp", 3); - } else { - setTimeout(fetch, interval); - } - retrycount++; - }); -} - -var upgrade = function() { - if(nextVersion) { - if(confirm("WARNING: If you have a M-BUS powered device (Pow-U), please keep USB power connected while upgrading.\n\nAre you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) { - $('#loading-indicator').show(); - window.location.href="/upgrade?version=" + nextVersion.tag_name; - } - } -} - -var loadTempSensors = function() { - $.ajax({ - url: '/temperature.json', - timeout: 10000, - dataType: 'json', - }).done(function(json) { - if($('#loading').length > 0) { - $('#loading').hide(); - - var list = $('#sensors'); - if(json.c > 0) { - list.empty(); - var temp = $.trim($('#temp-template').html()); - $.each(json.s, function(i, o) { - var item = temp.replace(/{{index}}/ig, o.i); - var item = item.replace(/{{address}}/ig, o.a); - var item = item.replace(/{{name}}/ig, o.n); - var item = item.replace(/{{value}}/ig, o.v > -50 && o.v < 127 ? o.v : "N/A"); - var item = item.replace(/{{common}}/ig, o.c ? "checked" : ""); - list.append(item); - }); - } else { - $('#notemp').show(); - } - } else { - $.each(json.s, function(i, o) { - $('#temp-'+o.i).html(o.v > -50 && o.v < 127 ? o.v : "N/A"); - }); - } - setTimeout(loadTempSensors, 10000); - }).fail(function() { - setTimeout(loadTempSensors, 60000); - $('#loading').hide(); - $('#error').show(); - }); -} \ No newline at end of file diff --git a/lib/ClassicUi/html/boot.css b/lib/ClassicUi/html/boot.css deleted file mode 100644 index 548ffbef..00000000 --- a/lib/ClassicUi/html/boot.css +++ /dev/null @@ -1,432 +0,0 @@ -/* Ripped necessary style from bootstrap 4.4.1 to make the page look good without internet access. Meant to be overridden by CSS from CDN */ -:root { - --blue: #007bff; - --indigo: #6610f2; - --purple: #6f42c1; - --pink: #e83e8c; - --red: #dc3545; - --orange: #fd7e14; - --yellow: #ffc107; - --green: #28a745; - --teal: #20c997; - --cyan: #17a2b8; - --white: #fff; - --gray: #6c757d; - --gray-dark: #343a40; - --primary: #007bff; - --secondary: #6c757d; - --success: #28a745; - --info: #17a2b8; - --warning: #ffc107; - --danger: #dc3545; - --light: #f8f9fa; - --dark: #343a40; - --breakpoint-xs: 0; - --breakpoint-sm: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --font-family-sans-serif: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; - --font-family-monospace: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; -} -html { - font-family: sans-serif; - line-height: 1.15; - -webkit-text-size-adjust: 100%; - -webkit-tap-highlight-color: transparent; - color: -internal-root-color; -} -body { - display: block; - margin: 8px; - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - text-align: left; - background-color: #fff; -} -.bg-white { - background-color: #fff!important; -} -.bg-light { - background-color: #f8f9fa!important; -} -.bg-purple { - background-color: var(--purple); -} -.mt-2, .my-2 { - margin-top: .5rem!important; -} -.p-3 { - padding: 1rem!important; -} -.mb-3, .my-3 { - margin-bottom: 1rem!important; -} -.mt-3, .my-3 { - margin-top: 1rem!important; -} -.mb-4, .my-4 { - margin-bottom: 1.5rem!important; -} -.shadow { - box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important; -} -.rounded { - border-radius: .25rem!important; -} -.container { - width: 100%; - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { - display: block; -} -main { - display: block; -} -.text-right { - text-align: right!important; -} -.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { - margin-bottom: .5rem; - font-weight: 500; - line-height: 1.2; -} -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: .5rem; -} -.h5, h5 { - font-size: 1.25rem; -} -.h6, h6 { - font-size: 1rem; -} -.row { - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} -.col, .col-1, .col-10, .col-11, .col-12, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-auto, .col-lg, .col-lg-1, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-auto, .col-md, .col-md-1, .col-md-10, .col-md-11, .col-md-12, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-auto, .col-sm, .col-sm-1, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-auto, .col-xl, .col-xl-1, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-auto { - position: relative; - width: 100%; - padding-right: 15px; - padding-left: 15px; -} -.col-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; -} -.d-none { - display: none!important; -} -.flex-row { - -ms-flex-direction: row!important; - flex-direction: row!important; -} - -.flex-column { - -ms-flex-direction: column!important; - flex-direction: column!important; -} -a { - color: #007bff; - text-decoration: none; - background-color: transparent; -} -.btn { - display: inline-block; - font-weight: 400; - color: #212529; - text-align: center; - vertical-align: middle; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color: transparent; - border: 1px solid transparent; - padding: .375rem .75rem; - font-size: 1rem; - line-height: 1.5; - border-radius: .25rem; - transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; -} -.btn-group-sm>.btn, .btn-sm { - padding: .25rem .5rem; - font-size: .875rem; - line-height: 1.5; - border-radius: .2rem; -} -.btn-primary { - color: #fff; - background-color: #007bff; - border-color: #007bff; -} -.navbar { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - padding: .5rem 1rem; -} -.navbar-dark .navbar-brand { - color: #fff; -} -.navbar-expand { - -ms-flex-flow: row nowrap; - flex-flow: row nowrap; - -ms-flex-pack: start; - justify-content: flex-start; -} -.navbar-nav { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.navbar-expand .navbar-nav { - -ms-flex-direction: row; - flex-direction: row; -} -.navbar-brand { - display: inline-block; - padding-top: .3125rem; - padding-bottom: .3125rem; - margin-right: 1rem; - font-size: 1.25rem; - line-height: inherit; - white-space: nowrap; -} -.navbar-dark .navbar-nav .nav-link { - color: rgba(255,255,255,.5); -} -.navbar-expand .navbar-nav .nav-link { - padding-right: .5rem; - padding-left: .5rem; -} -.navbar-nav .nav-link { - padding-right: 0; - padding-left: 0; -} -.nav-link { - display: block; - padding: .5rem 1rem; -} -.navbar-dark .navbar-nav .active>.nav-link, .navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .show>.nav-link { - color: #fff; -} -.form-group { - margin-bottom: 1rem; -} -.form-control { - display: block; - width: 100%; - height: calc(1.5em + .75rem + 2px); - padding: .375rem .75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #495057; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ced4da; - border-radius: .25rem; - transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out; -} -.form-control:disabled, .form-control[readonly] { - background-color: #e9ecef; - opacity: 1; -} -input:not([type="image" i]) { - box-sizing: border-box; -} -button, input { - overflow: visible; -} -button, input, optgroup, select, textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -input[type="radio"], input[type="checkbox"] { - box-sizing: border-box; - padding: 0; -} -.input-group { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -ms-flex-align: stretch; - align-items: stretch; - width: 100%; -} -.input-group-append { - margin-left: -1px; -} -.input-group-prepend { - margin-right: -1px; -} -.input-group-append, .input-group-prepend { - display: -ms-flexbox; - display: flex; -} -.input-group>.input-group-append>.btn, .input-group>.input-group-append>.input-group-text, .input-group>.input-group-prepend:first-child>.btn:not(:first-child), .input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child), .input-group>.input-group-prepend:not(:first-child)>.btn, .input-group>.input-group-prepend:not(:first-child)>.input-group-text { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle), .input-group>.input-group-append:last-child>.input-group-text:not(:last-child), .input-group>.input-group-append:not(:last-child)>.btn, .input-group>.input-group-append:not(:last-child)>.input-group-text, .input-group>.input-group-prepend>.btn, .input-group>.input-group-prepend>.input-group-text { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group>.custom-select:not(:first-child), .input-group>.form-control:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group-text { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: .375rem .75rem; - margin-bottom: 0; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #495057; - text-align: center; - white-space: nowrap; - background-color: #e9ecef; - border: 1px solid #ced4da; - border-radius: .25rem; -} -.input-group>.custom-select:not(:last-child), .input-group>.form-control:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group>.custom-file, .input-group>.custom-select, .input-group>.form-control, .input-group>.form-control-plaintext { - position: relative; - -ms-flex: 1 1 0%; - flex: 1 1 0%; - min-width: 0; - margin-bottom: 0; -} -hr { - margin-top: 1rem; - margin-bottom: 1rem; - border: 0; - border-top: 1px solid rgba(0,0,0,.1); - box-sizing: content-box; - height: 0; - overflow: visible; -} -ul { - display: block; - list-style-type: disc; - margin-block-start: 1em; - margin-block-end: 1em; - margin-inline-start: 0px; - margin-inline-end: 0px; - padding-inline-start: 40px; -} -li { - display: list-item; - text-align: -webkit-match-parent; -} -dl, ol, ul { - margin-top: 0; - margin-bottom: 1rem; -} - -@media (min-width: 576px) { - .container, .container-sm { - max-width: 540px; - } - .col-sm-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } -} -@media (min-width: 768px) { - .container, .container-md, .container-sm { - max-width: 720px; - } - .col-md-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .col-md-6 { - -ms-flex: 0 0 50%; - flex: 0 0 50%; - max-width: 50%; - } - .d-md-flex { - display: -ms-flexbox!important; - display: flex!important; - } - .flex-md-row { - -ms-flex-direction: row!important; - flex-direction: row!important; - } - .ml-md-auto, .mx-md-auto { - margin-left: auto!important; - } -} -@media (min-width: 992px) { - .container, .container-lg, .container-md, .container-sm { - max-width: 960px; - } - .col-lg-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } -} -@media (min-width: 1200px) { - .container, .container-lg, .container-md, .container-sm, .container-xl { - max-width: 1140px; - } - .col-xl-2 { - -ms-flex: 0 0 16.666667%; - flex: 0 0 16.666667%; - max-width: 16.666667%; - } - .col-xl-3 { - -ms-flex: 0 0 25%; - flex: 0 0 25%; - max-width: 25%; - } - .col-xl-4 { - -ms-flex: 0 0 33.333333%; - flex: 0 0 33.333333%; - max-width: 33.333333%; - } -} - -*, ::after, ::before { - box-sizing: border-box; -} diff --git a/lib/ClassicUi/html/configfile.html b/lib/ClassicUi/html/configfile.html deleted file mode 100644 index 94d3383d..00000000 --- a/lib/ClassicUi/html/configfile.html +++ /dev/null @@ -1,71 +0,0 @@ -
-
-
Download configuration
-
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- -
-
-
-
-
-
-
Upload configuration
-
-
-
-
- Upload -
-
- - -
-
-
-
-
-
- -
-
-
-
-
-
-
- Back -
-
diff --git a/lib/ClassicUi/html/data.json b/lib/ClassicUi/html/data.json deleted file mode 100644 index 02bf78d0..00000000 --- a/lib/ClassicUi/html/data.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "im" : %d, - "om" : %d, - "mf" : %d, - "i" : %d, - "e" : %d, - "ri" : %d, - "re" : %d, - "ic" : %.3f, - "ec" : %.3f, - "ric" : %.3f, - "rec" : %.3f, - "u1" : %.2f, - "u2" : %.2f, - "u3" : %.2f, - "i1" : %.2f, - "i2" : %.2f, - "i3" : %.2f, - "f" : %.2f, - "f1" : %.2f, - "f2" : %.2f, - "f3" : %.2f, - "v" : %.3f, - "r" : %d, - "t" : %.2f, - "u" : %u, - "m" : %u, - "em" : %d, - "hm" : %d, - "wm" : %d, - "mm" : %d, - "me" : %d, - "p" : %s, - "mt" : %d, - "ds" : %d, - "ea" : { - "x" : %.1f, - "p" : [ %s ], - "t" : %d, - "h" : { - "u" : %.2f, - "c" : %.2f, - "p" : %.2f, - "i" : %.2f - }, - "d" : { - "u" : %.2f, - "c" : %.2f, - "p" : %.2f, - "i" : %.2f - }, - "m" : { - "u" : %.2f, - "c" : %.2f, - "p" : %.2f, - "i" : %.2f - } - }, - "c" : %u -} \ No newline at end of file diff --git a/lib/ClassicUi/html/dayplot.json b/lib/ClassicUi/html/dayplot.json deleted file mode 100644 index ed782610..00000000 --- a/lib/ClassicUi/html/dayplot.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "i00" : %.2f, - "i01" : %.2f, - "i02" : %.2f, - "i03" : %.2f, - "i04" : %.2f, - "i05" : %.2f, - "i06" : %.2f, - "i07" : %.2f, - "i08" : %.2f, - "i09" : %.2f, - "i10" : %.2f, - "i11" : %.2f, - "i12" : %.2f, - "i13" : %.2f, - "i14" : %.2f, - "i15" : %.2f, - "i16" : %.2f, - "i17" : %.2f, - "i18" : %.2f, - "i19" : %.2f, - "i20" : %.2f, - "i21" : %.2f, - "i22" : %.2f, - "i23" : %.2f, - "e00" : %.2f, - "e01" : %.2f, - "e02" : %.2f, - "e03" : %.2f, - "e04" : %.2f, - "e05" : %.2f, - "e06" : %.2f, - "e07" : %.2f, - "e08" : %.2f, - "e09" : %.2f, - "e10" : %.2f, - "e11" : %.2f, - "e12" : %.2f, - "e13" : %.2f, - "e14" : %.2f, - "e15" : %.2f, - "e16" : %.2f, - "e17" : %.2f, - "e18" : %.2f, - "e19" : %.2f, - "e20" : %.2f, - "e21" : %.2f, - "e22" : %.2f, - "e23" : %.2f -} diff --git a/lib/ClassicUi/html/debugging.html b/lib/ClassicUi/html/debugging.html deleted file mode 100644 index 942b3cd7..00000000 --- a/lib/ClassicUi/html/debugging.html +++ /dev/null @@ -1,43 +0,0 @@ -
- !!WARNING!!
- Telnet debugging is not considered safe and should be switched off when not in use.
-
- !!WARNING!!
- Enabling debugging can cause sudden reboots. Do not leave this on unless you are debugging! -
-
- -
-
Debugging
-
-
- -
-
- -
-
-
- -
- -
-
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/delete.html b/lib/ClassicUi/html/delete.html deleted file mode 100644 index c03d0859..00000000 --- a/lib/ClassicUi/html/delete.html +++ /dev/null @@ -1,14 +0,0 @@ -
-
-
Are you sure you want to delete this file?
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/domoticz.html b/lib/ClassicUi/html/domoticz.html deleted file mode 100644 index fbc6d441..00000000 --- a/lib/ClassicUi/html/domoticz.html +++ /dev/null @@ -1,48 +0,0 @@ -
- -
-
-
-
- Electricity IDX -
- -
-
-
- Current (3 Phase) IDX -
- -
-
-
-
-
- Voltage L1 IDX -
- -
-
-
- Voltage L2 IDX -
- -
-
-
- Voltage L3 IDX -
- -
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/energyprice.json b/lib/ClassicUi/html/energyprice.json deleted file mode 100644 index 9231ba9c..00000000 --- a/lib/ClassicUi/html/energyprice.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "currency" : "%s", - "00" : %s, - "01" : %s, - "02" : %s, - "03" : %s, - "04" : %s, - "05" : %s, - "06" : %s, - "07" : %s, - "08" : %s, - "09" : %s, - "10" : %s, - "11" : %s, - "12" : %s, - "13" : %s, - "14" : %s, - "15" : %s, - "16" : %s, - "17" : %s, - "18" : %s, - "19" : %s, - "20" : %s, - "21" : %s, - "22" : %s, - "23" : %s, - "24" : %s, - "25" : %s, - "26" : %s, - "27" : %s, - "28" : %s, - "29" : %s, - "30" : %s, - "31" : %s, - "32" : %s, - "33" : %s, - "34" : %s, - "35" : %s -} diff --git a/lib/ClassicUi/html/firmware.html b/lib/ClassicUi/html/firmware.html deleted file mode 100644 index 0bdbf086..00000000 --- a/lib/ClassicUi/html/firmware.html +++ /dev/null @@ -1,50 +0,0 @@ -
- WARNING: Units powered by M-BUS (Pow-U) must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit. -
-
- Your board is using {chipset} chipset. Only upload firmware designed for this chipset. Failure to do so may result in non-functioning unit. - -
-
- When using URL, only a valid ESP OTA server response will be accepted. -
- -
-
-
-
-
-
- Upload file -
-
- - -
-
-
-
-
-
or
-
-
-
-
-
- Use URL -
- -
-
-
-
-
-
-
- Back -
-
- -
-
-
\ No newline at end of file diff --git a/lib/ClassicUi/html/foot.html b/lib/ClassicUi/html/foot.html deleted file mode 100644 index c22c948a..00000000 --- a/lib/ClassicUi/html/foot.html +++ /dev/null @@ -1,19 +0,0 @@ -
New version ! - view or click here to upgrade -
- - - - - - - - - - - - diff --git a/lib/ClassicUi/html/github.svg b/lib/ClassicUi/html/github.svg deleted file mode 100644 index f25b68d5..00000000 --- a/lib/ClassicUi/html/github.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - GitHub - - diff --git a/lib/ClassicUi/html/gpio.html b/lib/ClassicUi/html/gpio.html deleted file mode 100644 index 5bdf308b..00000000 --- a/lib/ClassicUi/html/gpio.html +++ /dev/null @@ -1,110 +0,0 @@ -
!!WARNING!!
Do not change anything here unless you know exactly what you are doing! Changing things here could cause the device to stop responding
-
- -
-
GPIO settings
-
-
-
- HAN -
- -
-
-
- LED -
- -
- -
-
-
-
- RGB -
- - - -
- -
-
-
-
- AP button -
- -
-
-
- Temperature -
- -
-
-
- Analog temp -
- -
-
-
- Vcc -
- -
-
-
- GND resistor -
- -
- -
-
-
-
- Vcc resistor -
- -
- -
-
-
-
- Multiplier -
- -
-
-
- Offset -
- -
-
-
- Boot limit -
- -
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/head.html b/lib/ClassicUi/html/head.html deleted file mode 100644 index bc831aa2..00000000 --- a/lib/ClassicUi/html/head.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - AMS reader - - - - - -
- diff --git a/lib/ClassicUi/html/index.html b/lib/ClassicUi/html/index.html deleted file mode 100644 index 4f230fde..00000000 --- a/lib/ClassicUi/html/index.html +++ /dev/null @@ -1,210 +0,0 @@ -
-
-
-
Up -
-
-
-
Temperature: -°C
-
-
-
ESP volt: -V
-
-
-
WiFi RSSI: -dBm
-
-
-
Free mem: -kb
-
-
-
-
-
-
- -
-
-
-
-
- - - - W -
- Import -
-
- -
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - - -
-
- Real time consumption
-
-
-
-
Hour
-
- kWh - -
-
-
-
-
-
Day
-
- kWh - -
-
-
-
-
-
Month
-
- kWh - -
-
-
-
-
-
Max
-
- / kWh -
-
-
-
- - Real time production
-
-
-
-
Hour
-
- kWh -
-
-
-
-
-
Day
-
- kWh -
-
-
-
-
-
Month
-
- kWh -
-
-
-
-
-
-
- - -
-
-
-
-
-
- -
-
MQTT communication error (-)
-
MQTT failed to connect
-
MQTT network timeout
-
MQTT connection denied
-
MQTT failed to subscribe
-
MQTT lost connection
-
-
- diff --git a/lib/ClassicUi/html/meter.html b/lib/ClassicUi/html/meter.html deleted file mode 100644 index 076fcd60..00000000 --- a/lib/ClassicUi/html/meter.html +++ /dev/null @@ -1,143 +0,0 @@ -
- -
-
Meter
-
-
-
-
- Manufacturer -
- -
-
-
-
-
- Model -
- -
-
-
-
-
- ID -
- -
-
-
-
-
-
-
- Baud rate -
- -
-
-
-
-
- Parity -
- -
-
-
-
- -
-
- -
-
-
-
-
- Distribution system -
- -
-
-
-
-
- Main fuse -
- -
- A -
-
-
-
-
-
- Production capacity -
- -
- kWp -
-
-
-
-
-
-
-
- Encryption key -
- -
-
-
-
-
- Authentication key -
- -
-
-
- -
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/meteradvanced.html b/lib/ClassicUi/html/meteradvanced.html deleted file mode 100644 index c5dd7d6e..00000000 --- a/lib/ClassicUi/html/meteradvanced.html +++ /dev/null @@ -1,49 +0,0 @@ -
- -
-
Multipliers
-
-
-
-
- Instant -
- -
-
-
-
-
- Voltage -
- -
-
-
-
-
- Amperage -
- -
-
-
-
-
- Accumulated -
- -
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/monthplot.json b/lib/ClassicUi/html/monthplot.json deleted file mode 100644 index e4271129..00000000 --- a/lib/ClassicUi/html/monthplot.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "i01" : %.2f, - "i02" : %.2f, - "i03" : %.2f, - "i04" : %.2f, - "i05" : %.2f, - "i06" : %.2f, - "i07" : %.2f, - "i08" : %.2f, - "i09" : %.2f, - "i10" : %.2f, - "i11" : %.2f, - "i12" : %.2f, - "i13" : %.2f, - "i14" : %.2f, - "i15" : %.2f, - "i16" : %.2f, - "i17" : %.2f, - "i18" : %.2f, - "i19" : %.2f, - "i20" : %.2f, - "i21" : %.2f, - "i22" : %.2f, - "i23" : %.2f, - "i24" : %.2f, - "i25" : %.2f, - "i26" : %.2f, - "i27" : %.2f, - "i28" : %.2f, - "i29" : %.2f, - "i30" : %.2f, - "i31" : %.2f, - "e01" : %.2f, - "e02" : %.2f, - "e03" : %.2f, - "e04" : %.2f, - "e05" : %.2f, - "e06" : %.2f, - "e07" : %.2f, - "e08" : %.2f, - "e09" : %.2f, - "e10" : %.2f, - "e11" : %.2f, - "e12" : %.2f, - "e13" : %.2f, - "e14" : %.2f, - "e15" : %.2f, - "e16" : %.2f, - "e17" : %.2f, - "e18" : %.2f, - "e19" : %.2f, - "e20" : %.2f, - "e21" : %.2f, - "e22" : %.2f, - "e23" : %.2f, - "e24" : %.2f, - "e25" : %.2f, - "e26" : %.2f, - "e27" : %.2f, - "e28" : %.2f, - "e29" : %.2f, - "e30" : %.2f, - "e31" : %.2f -} diff --git a/lib/ClassicUi/html/mqtt.html b/lib/ClassicUi/html/mqtt.html deleted file mode 100644 index 8871b3d9..00000000 --- a/lib/ClassicUi/html/mqtt.html +++ /dev/null @@ -1,138 +0,0 @@ -
- -
-
MQTT
- -
-
-
-
- Host -
- -
-
-
-
-
- Port -
- -
-
-
-
-
- Client ID -
- -
-
-
-
-
- Publish topic -
- -
-
-
-
-
- Username -
- -
-
-
-
-
- Password -
- -
-
-
-
-
- Payload -
- -
-
-
- -
-
-
-
-
-
- -
-
-
-
- CA -
-
- - Upload - - - Delete - -
-
-
-
-
-
- Certificate -
-
- - Upload - - - Delete - -
-
-
-
-
-
- Private key -
-
- - Upload - - - Delete - -
-
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/notfound.html b/lib/ClassicUi/html/notfound.html deleted file mode 100644 index 5f251d72..00000000 --- a/lib/ClassicUi/html/notfound.html +++ /dev/null @@ -1 +0,0 @@ -
Page not found
diff --git a/lib/ClassicUi/html/ntp.html b/lib/ClassicUi/html/ntp.html deleted file mode 100644 index 27080e9d..00000000 --- a/lib/ClassicUi/html/ntp.html +++ /dev/null @@ -1,54 +0,0 @@ -
- -
-
NTP
- -
-
-
-
- Timezone -
- -
-
-
-
-
- Summertime offset -
- -
-
-
-
-
- Server -
- -
-
-
-
- -
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/priceapi.html b/lib/ClassicUi/html/priceapi.html deleted file mode 100644 index 60dc4e6f..00000000 --- a/lib/ClassicUi/html/priceapi.html +++ /dev/null @@ -1,86 +0,0 @@ -
- -
-
Price API
-
-
-
-
- Region -
- -
-
-
-
-
- Currency -
- -
-
-
-
-
- Multiplier -
- -
-
-
-
-
- ENTSO-E token -
- -
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/reset.html b/lib/ClassicUi/html/reset.html deleted file mode 100644 index 1438eb21..00000000 --- a/lib/ClassicUi/html/reset.html +++ /dev/null @@ -1,14 +0,0 @@ -
-
-
Are you sure you want reset this device to factory settings? ALL configuration will be erased!
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/restart.html b/lib/ClassicUi/html/restart.html deleted file mode 100644 index fb5c277d..00000000 --- a/lib/ClassicUi/html/restart.html +++ /dev/null @@ -1,14 +0,0 @@ -
-
-
Are you sure you want restart?
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/restartwait.html b/lib/ClassicUi/html/restartwait.html deleted file mode 100644 index 3d0071fd..00000000 --- a/lib/ClassicUi/html/restartwait.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - - AMS reader - Restarting, please wait - - - - -
- -
- Device is rebooting. You will be redirected to the main page when it is available again. -
-
Firmware upgrade in progress, DO NOT disconnect power from the device. You will be redirected to the main page when firmware upgrade is complete.
-
- - - diff --git a/lib/ClassicUi/html/setup.html b/lib/ClassicUi/html/setup.html deleted file mode 100644 index 3c0b1e37..00000000 --- a/lib/ClassicUi/html/setup.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - AMS reader - Setup - - - - -
- -
-
-
-
-
Hardware
- -
-
-
-
-
WiFi
-
-
-
-
- SSID -
- -
-
-
-
-
- PSK -
- -
-
-
-
-
- Hostname -
- -
-
-
- -
-
-
-
-
-
- IP -
- -
-
-
-
-
- Subnet -
- -
-
-
-
-
- Gateway -
- -
-
-
-
-
- DNS -
- -
-
-
-
-
-
-
-
- -
-
-
-
- - - diff --git a/lib/ClassicUi/html/temperature.html b/lib/ClassicUi/html/temperature.html deleted file mode 100644 index 764b8a72..00000000 --- a/lib/ClassicUi/html/temperature.html +++ /dev/null @@ -1,48 +0,0 @@ - - -
- -
-
Loading temperature sensors
- - -
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/tempsensor.json b/lib/ClassicUi/html/tempsensor.json deleted file mode 100644 index 573b756c..00000000 --- a/lib/ClassicUi/html/tempsensor.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "i" : %d, - "a" : "%s", - "n" : "%s", - "c" : %d, - "v" : %.1f -}, \ No newline at end of file diff --git a/lib/ClassicUi/html/thresholds.html b/lib/ClassicUi/html/thresholds.html deleted file mode 100644 index 542d3416..00000000 --- a/lib/ClassicUi/html/thresholds.html +++ /dev/null @@ -1,129 +0,0 @@ -
- -
-
Tariff thresholds
-
-
-
-
- 1 -
- -
- kWh -
-
-
-
-
-
- 2 -
- -
- kWh -
-
-
-
-
-
- 3 -
- -
- kWh -
-
-
-
-
-
- 4 -
- -
- kWh -
-
-
-
-
-
- 5 -
- -
- kWh -
-
-
-
-
-
- 6 -
- -
- kWh -
-
-
-
-
-
- 7 -
- -
- kWh -
-
-
-
-
-
- 8 -
- -
- kWh -
-
-
-
-
-
- 9 -
- -
- kWh -
-
-
-
-
-
-
-
- Average of top -
- -
- hours -
-
-
-
-
-
-
-
- Back -
-
- -
-
-
\ No newline at end of file diff --git a/lib/ClassicUi/html/upload.html b/lib/ClassicUi/html/upload.html deleted file mode 100644 index e87cd4eb..00000000 --- a/lib/ClassicUi/html/upload.html +++ /dev/null @@ -1,26 +0,0 @@ -
-
-
-
-
-
- Upload -
-
- - -
-
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/web.html b/lib/ClassicUi/html/web.html deleted file mode 100644 index 34ea2052..00000000 --- a/lib/ClassicUi/html/web.html +++ /dev/null @@ -1,45 +0,0 @@ -
- -
-
Web
-
-
-
-
- Security -
- -
-
-
-
-
- Username -
- -
-
-
-
-
- Password -
- -
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/html/wifi.html b/lib/ClassicUi/html/wifi.html deleted file mode 100644 index a99adc16..00000000 --- a/lib/ClassicUi/html/wifi.html +++ /dev/null @@ -1,117 +0,0 @@ -
- -
-
WiFi
-
-
-
-
- SSID -
- -
-
-
-
-
- PSK -
- -
-
-
-
-
- Hostname -
- -
- -
-
-
-
- -
-
-
-
-
-
- IP -
- -
-
-
-
-
- Netmask -
- -
-
-
-
-
- Gateway -
- -
-
-
-
-
- DNS 1 -
- -
-
-
-
-
- DNS 2 -
- -
-
- -
-
-
- Power -
- -
- dBm -
-
-
- -
-
-
- Power saving -
- -
-
-
-
-
-
-
- Back -
-
- -
-
-
diff --git a/lib/ClassicUi/include/.gitignore b/lib/ClassicUi/include/.gitignore deleted file mode 100644 index 1530ce82..00000000 --- a/lib/ClassicUi/include/.gitignore +++ /dev/null @@ -1 +0,0 @@ -root/*.h diff --git a/lib/ClassicUi/include/AmsWebHeaders.h b/lib/ClassicUi/include/AmsWebHeaders.h deleted file mode 100644 index f8fe134f..00000000 --- a/lib/ClassicUi/include/AmsWebHeaders.h +++ /dev/null @@ -1,15 +0,0 @@ -static const char HEADER_CACHE_CONTROL[] PROGMEM = "Cache-Control"; -static const char HEADER_PRAGMA[] PROGMEM = "Pragma"; -static const char HEADER_EXPIRES[] PROGMEM = "Expires"; -static const char HEADER_AUTHENTICATE[] PROGMEM = "WWW-Authenticate"; -static const char HEADER_LOCATION[] PROGMEM = "Location"; - -static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate"; -static const char CACHE_1HR[] PROGMEM = "public, max-age=3600"; -static const char PRAGMA_NO_CACHE[] PROGMEM = "no-cache"; -static const char EXPIRES_OFF[] PROGMEM = "-1"; -static const char AUTHENTICATE_BASIC[] PROGMEM = "Basic realm=\"Secure Area\""; - -static const char MIME_PLAIN[] PROGMEM = "text/plain"; -static const char MIME_HTML[] PROGMEM = "text/html"; -static const char MIME_JSON[] PROGMEM = "application/json"; diff --git a/lib/ClassicUi/include/AmsWebServer.h b/lib/ClassicUi/include/AmsWebServer.h deleted file mode 100644 index b6d3decf..00000000 --- a/lib/ClassicUi/include/AmsWebServer.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef _AMSWEBSERVER_h -#define _AMSWEBSERVER_h - -#define BOOTSTRAP_URL "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" - -#include "Arduino.h" -#include -#include "AmsConfiguration.h" -#include "HwTools.h" -#include "AmsData.h" -#include "AmsStorage.h" -#include "AmsDataStorage.h" -#include "EnergyAccounting.h" -#include "Uptime.h" -#include "RemoteDebug.h" -#include "EntsoeApi.h" - -#if defined(ESP8266) - #include - #include - #include - #include -#elif defined(ESP32) // ARDUINO_ARCH_ESP32 - #include - #include - #include - #include -#else - #warning "Unsupported board type" -#endif - -#include "LittleFS.h" - -class AmsWebServer { -public: - AmsWebServer(uint8_t* buf, RemoteDebug* Debug, HwTools* hw); - void setup(AmsConfiguration*, GpioConfig*, MeterConfig*, AmsData*, AmsDataStorage*, EnergyAccounting*); - void loop(); - void setMqtt(MQTTClient* mqtt); - void setTimezone(Timezone* tz); - void setMqttEnabled(bool); - void setEntsoeApi(EntsoeApi* eapi); - -private: - RemoteDebug* debugger; - bool mqttEnabled = false; - int maxPwr = 0; - HwTools* hw; - Timezone* tz; - EntsoeApi* eapi = NULL; - AmsConfiguration* config; - GpioConfig* gpioConfig; - MeterConfig* meterConfig; - WebConfig webConfig; - AmsData* meterState; - AmsDataStorage* ds; - EnergyAccounting* ea = NULL; - MQTTClient* mqtt = NULL; - bool uploading = false; - File file; - bool performRestart = false; - bool performUpgrade = false; - bool rebootForUpgrade = false; - #if defined(AMS2MQTT_FIRMWARE_URL) - String customFirmwareUrl = AMS2MQTT_FIRMWARE_URL; - #else - String customFirmwareUrl; - #endif - - static const uint16_t BufferSize = 2048; - char* buf; - -#if defined(ESP8266) - ESP8266WebServer server; -#elif defined(ESP32) // ARDUINO_ARCH_ESP32 - WebServer server; -#endif - - bool checkSecurity(byte level); - - void indexHtml(); - void applicationJs(); - void temperature(); - void temperaturePost(); - void temperatureJson(); - void configMeterHtml(); - void configMeterAdvancedHtml(); - void configWifiHtml(); - void configMqttHtml(); - void configWebHtml(); - void configDomoticzHtml(); - void configPriceApiHtml(); - void configNtpHtml(); - void configGpioHtml(); - void configDebugHtml(); - void configThresholdsHtml(); - void bootCss(); - void githubSvg(); - void dataJson(); - void dayplotJson(); - void monthplotJson(); - void energyPriceJson(); - void configFileHtml(); - void configFileDownload(); - void configFileUpload(); - - void handleSetup(); - void handleSave(); - - String getSerialSelectOptions(int selected); - void firmwareHtml(); - void firmwarePost(); - void firmwareUpload(); - void firmwareDownload(); - void restartHtml(); - void restartPost(); - void restartWaitHtml(); - void isAliveCheck(); - - void uploadHtml(const char* label, const char* action, const char* menu); - void deleteHtml(const char* label, const char* action, const char* menu); - HTTPUpload& uploadFile(const char* path); - void deleteFile(const char* path); - void uploadPost(); - void mqttCa(); - void mqttCaUpload(); - void mqttCaDelete(); - void mqttCert(); - void mqttCertUpload(); - void mqttCertDelete(); - void mqttKey(); - void mqttKeyUpload(); - void mqttKeyDelete(); - - void factoryResetHtml(); - void factoryResetPost(); - - void notFound(); - - void printD(String fmt, ...); - void printI(String fmt, ...); - void printW(String fmt, ...); - void printE(String fmt, ...); -}; - -#endif diff --git a/lib/ClassicUi/scripts/generate_includes.py b/lib/ClassicUi/scripts/generate_includes.py deleted file mode 100644 index bb5efbeb..00000000 --- a/lib/ClassicUi/scripts/generate_includes.py +++ /dev/null @@ -1,80 +0,0 @@ -import os -import re -import shutil -import subprocess - -try: - from css_html_js_minify import html_minify, js_minify, css_minify -except: - from SCons.Script import ( - ARGUMENTS, - COMMAND_LINE_TARGETS, - DefaultEnvironment, - ) - env = DefaultEnvironment() - - env.Execute( - env.VerboseAction( - '$PYTHONEXE -m pip install "css_html_js_minify" ', - "Installing Python dependencies", - ) - ) - try: - from css_html_js_minify import html_minify, js_minify, css_minify - except: - print("WARN: Unable to load minifier") - - -webroot = "lib/ClassicUi/html" -srcroot = "lib/ClassicUi/include/root" - -version = os.environ.get('GITHUB_TAG') -if version == None: - try: - result = subprocess.run(['git','rev-parse','--short','HEAD'], capture_output=True, check=False) - if result.returncode == 0: - version = result.stdout.decode('utf-8').strip() - else: - version = "SNAPSHOT" - except: - version = "SNAPSHOT" - -if os.path.exists(srcroot): - shutil.rmtree(srcroot) - os.mkdir(srcroot) -else: - os.mkdir(srcroot) - -for filename in os.listdir(webroot): - basename = re.sub("[^0-9a-zA-Z]+", "_", filename) - - srcfile = webroot + "/" + filename - dstfile = srcroot + "/" + basename + ".h" - - varname = basename.upper() - - with open(srcfile, encoding="utf-8") as f: - content = f.read().replace("${version}", version) - - try: - if filename.endswith(".html"): - content = html_minify(content) - elif filename.endswith(".css"): - content = css_minify(content) - elif (filename.endswith(".js") and filename != 'gaugemeter.js') or filename.endswith(".json"): - content = js_minify(content) - except: - print("WARN: Unable to minify") - - with open(dstfile, "w") as dst: - dst.write("static const char ") - dst.write(varname) - dst.write("[] PROGMEM = R\"==\"==(") - dst.write(content) - dst.write(")==\"==\";\n") - dst.write("const int "); - dst.write(varname) - dst.write("_LEN PROGMEM = "); - dst.write(str(len(content))) - dst.write(";"); - \ No newline at end of file diff --git a/lib/ClassicUi/src/AmsWebServer.cpp b/lib/ClassicUi/src/AmsWebServer.cpp deleted file mode 100644 index cdb778fe..00000000 --- a/lib/ClassicUi/src/AmsWebServer.cpp +++ /dev/null @@ -1,2496 +0,0 @@ -#include "AmsWebServer.h" -#include "AmsWebHeaders.h" -#include "version.h" -#include "hexutils.h" -#include "AmsData.h" - -#if defined(ESP32) -#include -#endif - -#include "root/head_html.h" -#include "root/foot_html.h" -#include "root/index_html.h" -#include "root/application_js.h" -#include "root/setup_html.h" -#include "root/meter_html.h" -#include "root/wifi_html.h" -#include "root/mqtt_html.h" -#include "root/web_html.h" -#include "root/domoticz_html.h" -#include "root/priceapi_html.h" -#include "root/ntp_html.h" -#include "root/gpio_html.h" -#include "root/debugging_html.h" -#include "root/restart_html.h" -#include "root/restartwait_html.h" -#include "root/boot_css.h" -#include "root/github_svg.h" -#include "root/upload_html.h" -#include "root/firmware_html.h" -#include "root/delete_html.h" -#include "root/reset_html.h" -#include "root/temperature_html.h" -#include "root/notfound_html.h" -#include "root/data_json.h" -#include "root/tempsensor_json.h" -#include "root/dayplot_json.h" -#include "root/monthplot_json.h" -#include "root/energyprice_json.h" -#include "root/thresholds_html.h" -#include "root/configfile_html.h" -#include "root/meteradvanced_html.h" - -#include "base64.h" - -AmsWebServer::AmsWebServer(uint8_t* buf, RemoteDebug* Debug, HwTools* hw) { - this->debugger = Debug; - this->hw = hw; - this->buf = (char*) buf; -} - -void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, MeterConfig* meterConfig, AmsData* meterState, AmsDataStorage* ds, EnergyAccounting* ea) { - this->config = config; - this->gpioConfig = gpioConfig; - this->meterConfig = meterConfig; - this->meterState = meterState; - this->ds = ds; - this->ea = ea; - - snprintf_P(buf, 32, PSTR("/application-%s.js"), VERSION); - - server.on(F("/"), HTTP_GET, std::bind(&AmsWebServer::indexHtml, this)); - server.on(F("/"), HTTP_POST, std::bind(&AmsWebServer::handleSetup, this)); - server.on(buf, HTTP_GET, std::bind(&AmsWebServer::applicationJs, this)); - server.on(F("/temperature"), HTTP_GET, std::bind(&AmsWebServer::temperature, this)); - server.on(F("/temperature"), HTTP_POST, std::bind(&AmsWebServer::temperaturePost, this)); - server.on(F("/temperature.json"), HTTP_GET, std::bind(&AmsWebServer::temperatureJson, this)); - server.on(F("/meter"), HTTP_GET, std::bind(&AmsWebServer::configMeterHtml, this)); - server.on(F("/meteradvanced"), HTTP_GET, std::bind(&AmsWebServer::configMeterAdvancedHtml, this)); - server.on(F("/wifi"), HTTP_GET, std::bind(&AmsWebServer::configWifiHtml, this)); - server.on(F("/mqtt"), HTTP_GET, std::bind(&AmsWebServer::configMqttHtml, this)); - server.on(F("/web"), HTTP_GET, std::bind(&AmsWebServer::configWebHtml, this)); - server.on(F("/domoticz"),HTTP_GET, std::bind(&AmsWebServer::configDomoticzHtml, this)); - server.on(F("/priceapi"),HTTP_GET, std::bind(&AmsWebServer::configPriceApiHtml, this)); - server.on(F("/thresholds"),HTTP_GET, std::bind(&AmsWebServer::configThresholdsHtml, this)); - server.on(F("/boot.css"), HTTP_GET, std::bind(&AmsWebServer::bootCss, this)); - server.on(F("/github.svg"), HTTP_GET, std::bind(&AmsWebServer::githubSvg, this)); - server.on(F("/data.json"), HTTP_GET, std::bind(&AmsWebServer::dataJson, this)); - server.on(F("/dayplot.json"), HTTP_GET, std::bind(&AmsWebServer::dayplotJson, this)); - server.on(F("/monthplot.json"), HTTP_GET, std::bind(&AmsWebServer::monthplotJson, this)); - server.on(F("/energyprice.json"), HTTP_GET, std::bind(&AmsWebServer::energyPriceJson, this)); - server.on(F("/configfile"),HTTP_GET, std::bind(&AmsWebServer::configFileHtml, this)); - server.on(F("/configfile"), HTTP_POST, std::bind(&AmsWebServer::uploadPost, this), std::bind(&AmsWebServer::configFileUpload, this)); - server.on(F("/configfile.cfg"),HTTP_GET, std::bind(&AmsWebServer::configFileDownload, this)); - - server.on(F("/save"), HTTP_POST, std::bind(&AmsWebServer::handleSave, this)); - - server.on(F("/ntp"), HTTP_GET, std::bind(&AmsWebServer::configNtpHtml, this)); - server.on(F("/gpio"), HTTP_GET, std::bind(&AmsWebServer::configGpioHtml, this)); - server.on(F("/debugging"), HTTP_GET, std::bind(&AmsWebServer::configDebugHtml, this)); - - server.on(F("/firmware"), HTTP_GET, std::bind(&AmsWebServer::firmwareHtml, this)); - server.on(F("/firmware"), HTTP_POST, std::bind(&AmsWebServer::firmwarePost, this), std::bind(&AmsWebServer::firmwareUpload, this)); - server.on(F("/upgrade"), HTTP_GET, std::bind(&AmsWebServer::firmwareDownload, this)); - server.on(F("/restart"), HTTP_GET, std::bind(&AmsWebServer::restartHtml, this)); - server.on(F("/restart"), HTTP_POST, std::bind(&AmsWebServer::restartPost, this)); - server.on(F("/restart-wait"), HTTP_GET, std::bind(&AmsWebServer::restartWaitHtml, this)); - server.on(F("/is-alive"), HTTP_GET, std::bind(&AmsWebServer::isAliveCheck, this)); - - server.on(F("/mqtt-ca"), HTTP_GET, std::bind(&AmsWebServer::mqttCa, this)); - server.on(F("/mqtt-ca"), HTTP_POST, std::bind(&AmsWebServer::mqttCaDelete, this), std::bind(&AmsWebServer::mqttCaUpload, this)); - server.on(F("/mqtt-cert"), HTTP_GET, std::bind(&AmsWebServer::mqttCert, this)); - server.on(F("/mqtt-cert"), HTTP_POST, std::bind(&AmsWebServer::mqttCertDelete, this), std::bind(&AmsWebServer::mqttCertUpload, this)); - server.on(F("/mqtt-key"), HTTP_GET, std::bind(&AmsWebServer::mqttKey, this)); - server.on(F("/mqtt-key"), HTTP_POST, std::bind(&AmsWebServer::mqttKeyDelete, this), std::bind(&AmsWebServer::mqttKeyUpload, this)); - - server.on(F("/reset"), HTTP_GET, std::bind(&AmsWebServer::factoryResetHtml, this)); - server.on(F("/reset"), HTTP_POST, std::bind(&AmsWebServer::factoryResetPost, this)); - - server.onNotFound(std::bind(&AmsWebServer::notFound, this)); - - server.begin(); // Web server start - - config->getWebConfig(webConfig); - MqttConfig mqttConfig; - config->getMqttConfig(mqttConfig); - mqttEnabled = strlen(mqttConfig.host) > 0; -} - -void AmsWebServer::setMqtt(MQTTClient* mqtt) { - this->mqtt = mqtt; -} - -void AmsWebServer::setTimezone(Timezone* tz) { - this->tz = tz; -} - -void AmsWebServer::setMqttEnabled(bool enabled) { - mqttEnabled = enabled; -} - -void AmsWebServer::setEntsoeApi(EntsoeApi* eapi) { - this->eapi = eapi; -} - -void AmsWebServer::loop() { - server.handleClient(); - - if(maxPwr == 0 && meterState->getListType() > 1 && meterConfig->mainFuse > 0 && meterConfig->distributionSystem > 0) { - int voltage = meterConfig->distributionSystem == 2 ? 400 : 230; - if(meterState->isThreePhase()) { - maxPwr = meterConfig->mainFuse * sqrt(3) * voltage; - } else if(meterState->isTwoPhase()) { - maxPwr = meterConfig->mainFuse * voltage; - } else { - maxPwr = meterConfig->mainFuse * 230; - } - } -} - -bool AmsWebServer::checkSecurity(byte level) { - bool access = WiFi.getMode() == WIFI_AP || webConfig.security < level; - if(!access && webConfig.security >= level && server.hasHeader(F("Authorization"))) { - String expectedAuth = String(webConfig.username) + ":" + String(webConfig.password); - - String providedPwd = server.header(F("Authorization")); - providedPwd.replace(F("Basic "), F("")); - - #if defined(ESP8266) - String expectedBase64 = base64::encode(expectedAuth, false); - #elif defined(ESP32) - String expectedBase64 = base64::encode(expectedAuth); - #endif - - debugger->printf_P(PSTR("Expected auth: %s\n"), expectedBase64.c_str()); - debugger->printf_P(PSTR("Provided auth: %s\n"), providedPwd.c_str()); - - access = providedPwd.equals(expectedBase64); - } - - if(!access) { - server.sendHeader(HEADER_AUTHENTICATE, AUTHENTICATE_BASIC); - server.setContentLength(0); - server.send_P(401, MIME_HTML, PSTR("")); - } - return access; -} - -void AmsWebServer::temperature() { - printD(F("Serving /temperature.html over http...")); - - if(!checkSecurity(2)) - return; - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(HEAD_HTML_LEN + TEMPERATURE_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent_P(TEMPERATURE_HTML); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::temperaturePost() { - if(!checkSecurity(1)) - return; - - printD(F("Saving temperature sensors...")); - for(int i = 0; i < 32; i++) { - if(!server.hasArg("sensor" + String(i, DEC))) break; - String address = server.arg("sensor" + String(i, DEC)); - String name = server.arg("sensor" + String(i, DEC) + "name").substring(0,16); - bool common = server.hasArg("sensor" + String(i, DEC) + "common") && server.arg("sensor" + String(i, DEC) + "common") == F("true"); - if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf("Addr: %s, name: %s\n", address.c_str(), name.c_str()); - } - uint8_t hexStr[8]; - fromHex(hexStr, address, 8); - config->updateTempSensorConfig(hexStr, name.c_str(), common); - delay(1); - } - - //if (debugger->isActive(RemoteDebug::DEBUG)) config->print(debugger); - if(config->save()) { - printD(F("Successfully saved temperature sensors")); - server.sendHeader(HEADER_LOCATION, F("/temperature"), true); - server.send (302, MIME_PLAIN, F("")); - } else { - printE(F("Error saving configuration")); - server.send_P(500, MIME_HTML, PSTR("

Error saving configuration!

")); - } -} - -void AmsWebServer::temperatureJson() { - printD(F("Serving /temperature.json over http...")); - - if(!checkSecurity(2)) - return; - - int count = hw->getTempSensorCount(); - snprintf_P(buf, 16, PSTR("{\"c\":%d,\"s\":["), count); - - for(int i = 0; i < count; i++) { - TempSensorData* data = hw->getTempSensorData(i); - if(data == NULL) continue; - - TempSensorConfig* conf = config->getTempSensorConfig(data->address); - char* pos = buf+strlen(buf); - snprintf_P(pos, 72, TEMPSENSOR_JSON, - i, - toHex(data->address, 8).c_str(), - conf == NULL ? "" : String(conf->name).substring(0,16).c_str(), - conf == NULL || conf->common ? 1 : 0, - data->lastRead - ); - delay(10); - } - char* pos = buf+strlen(buf); - snprintf_P(count == 0 ? pos : pos-1, 8, PSTR("]}")); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf)); - server.send(200, MIME_JSON, buf); -} - -void AmsWebServer::indexHtml() { - printD(F("Serving /index.html over http...")); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - if(WiFi.getMode() == WIFI_AP) { - SystemConfig sys; - config->getSystemConfig(sys); - - WiFiConfig wifi; - config->clearWifi(wifi); - - String html = String((const __FlashStringHelper*) SETUP_HTML); - for(int i = 0; i<255; i++) { - html.replace("${config.boardType" + String(i) + "}", sys.boardType == i ? F("selected") : F("")); - } - html.replace(F("${config.wifiSsid}"), wifi.ssid); - html.replace(F("${config.wifiPassword}"), wifi.psk); - html.replace(F("${config.wifiStaticIp}"), strlen(wifi.ip) > 0 ? F("checked") : F("")); - html.replace(F("${config.wifiIp}"), wifi.ip); - html.replace(F("${config.wifiGw}"), wifi.gateway); - html.replace(F("${config.wifiSubnet}"), wifi.subnet); - html.replace(F("${config.wifiDns1}"), wifi.dns1); - html.replace(F("${config.wifiDns2}"), wifi.dns2); - html.replace(F("${config.wifiHostname}"), wifi.hostname); - server.send(200, MIME_HTML, html); - } else { - if(!checkSecurity(2)) - return; - server.setContentLength(INDEX_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - - server.sendContent_P(INDEX_HTML); - server.sendContent_P(FOOT_HTML); - } -} - -void AmsWebServer::applicationJs() { - printD(F("Serving /application.js over http...")); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); - server.send_P(200, PSTR("application/javascript"), APPLICATION_JS); -} - -void AmsWebServer::configMeterHtml() { - printD(F("Serving /meter.html over http...")); - - if(!checkSecurity(1)) - return; - - String html = String((const __FlashStringHelper*) METER_HTML); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - String manufacturer; - switch(meterState->getMeterType()) { - case AmsTypeAidon: - manufacturer = F("Aidon"); - break; - case AmsTypeKaifa: - manufacturer = F("Kaifa"); - break; - case AmsTypeKamstrup: - manufacturer = F("Kamstrup"); - break; - case AmsTypeIskra: - manufacturer = F("Iskra"); - break; - case AmsTypeLandisGyr: - manufacturer = F("Landis+Gyr"); - break; - case AmsTypeSagemcom: - manufacturer = F("Sagemcom"); - break; - case AmsTypeLng: - manufacturer = F("L&G"); - break; - default: - manufacturer = F("Unknown"); - break; - } - - html.replace(F("{maf}"), manufacturer); - html.replace(F("{mod}"), meterState->getMeterModel()); - html.replace(F("{mid}"), meterState->getMeterId()); - html.replace(F("{b}"), String(meterConfig->baud)); - html.replace(F("{b300}"), meterConfig->baud == 300 ? F("selected") : F("")); - html.replace(F("{b2400}"), meterConfig->baud == 2400 ? F("selected") : F("")); - html.replace(F("{b4800}"), meterConfig->baud == 4800 ? F("selected") : F("")); - html.replace(F("{b9600}"), meterConfig->baud == 9600 ? F("selected") : F("")); - html.replace(F("{b19200}"), meterConfig->baud == 19200 ? F("selected") : F("")); - html.replace(F("{b38400}"), meterConfig->baud == 38400 ? F("selected") : F("")); - html.replace(F("{b57600}"), meterConfig->baud == 57600 ? F("selected") : F("")); - html.replace(F("{b115200}"), meterConfig->baud == 115200 ? F("selected") : F("")); - html.replace(F("{c}"), String(meterConfig->baud)); - html.replace(F("{c2}"), meterConfig->parity == 2 ? F("selected") : F("")); - html.replace(F("{c3}"), meterConfig->parity == 3 ? F("selected") : F("")); - html.replace(F("{c10}"), meterConfig->parity == 10 ? F("selected") : F("")); - html.replace(F("{c11}"), meterConfig->parity == 11 ? F("selected") : F("")); - html.replace(F("{i}"), meterConfig->invert ? F("checked") : F("")); - html.replace(F("{d}"), String(meterConfig->distributionSystem)); - for(int i = 0; i<3; i++) { - html.replace("{d" + String(i) + "}", meterConfig->distributionSystem == i ? F("selected") : F("")); - } - html.replace(F("{f}"), String(meterConfig->mainFuse)); - html.replace(F("{p}"), String(meterConfig->productionCapacity)); - - if(meterConfig->encryptionKey[0] != 0x00) { - String encryptionKeyHex = "0x"; - encryptionKeyHex += toHex(meterConfig->encryptionKey, 16); - html.replace(F("{e}"), encryptionKeyHex); - - String authenticationKeyHex = "0x"; - authenticationKeyHex += toHex(meterConfig->authenticationKey, 16); - html.replace(F("{a}"), authenticationKeyHex); - } else { - html.replace(F("{e}"), F("")); - html.replace(F("{a}"), F("")); - } - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configMeterAdvancedHtml() { - printD(F("Serving /meteradvanced.html over http...")); - - if(!checkSecurity(1)) - return; - - snprintf_P(buf, BufferSize, METERADVANCED_HTML, - meterConfig->wattageMultiplier / 1000.0, - meterConfig->voltageMultiplier / 1000.0, - meterConfig->amperageMultiplier / 1000.0, - meterConfig->accumulatedMultiplier / 1000.0 - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf) + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(buf); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configWifiHtml() { - printD(F("Serving /wifi.html over http...")); - - if(!checkSecurity(1)) - return; - - String html = String((const __FlashStringHelper*) WIFI_HTML); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - WiFiConfig wifi; - config->getWiFiConfig(wifi); - - html.replace(F("{s}"), wifi.ssid); - html.replace(F("{p}"), wifi.psk); - if(strlen(wifi.ip) > 0) { - html.replace(F("{st}"), F("checked")); - html.replace(F("{i}"), wifi.ip); - html.replace(F("{g}"), wifi.gateway); - html.replace(F("{sn}"), wifi.subnet); - html.replace(F("{d1}"), wifi.dns1); - html.replace(F("{d2}"), wifi.dns2); - } else { - html.replace(F("{st}"), F("")); - html.replace(F("{i}"), WiFi.localIP().toString()); - html.replace(F("{g}"), WiFi.gatewayIP().toString()); - html.replace(F("{sn}"), WiFi.subnetMask().toString()); - html.replace(F("{d1}"), WiFi.dnsIP().toString()); - html.replace(F("{d2}"), F("")); - } - html.replace(F("{h}"), wifi.hostname); - html.replace(F("{m}"), wifi.mdns ? F("checked") : F("")); - html.replace(F("{w}"), String(wifi.power / 10.0, 1)); - html.replace(F("{z0}"), wifi.sleep == 0 ? "selected" : ""); - html.replace(F("{z1}"), wifi.sleep == 1 ? "selected" : ""); - html.replace(F("{z2}"), wifi.sleep == 2 ? "selected" : ""); - #if defined(ESP32) - html.replace(F("{wm}"), "19.5"); - #elif defined(ESP8266) - html.replace(F("{wm}"), "20.5"); - #endif - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configMqttHtml() { - printD(F("Serving /mqtt.html over http...")); - - if(!checkSecurity(1)) - return; - - String html = String((const __FlashStringHelper*) MQTT_HTML); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - MqttConfig mqtt; - config->getMqttConfig(mqtt); - - html.replace(F("{m}"), strlen(mqtt.host) == 0 ? F("") : F("checked")); - html.replace(F("{h}"), mqtt.host); - if(mqtt.port > 0) { - html.replace(F("{p}"), String(mqtt.port)); - } else { - html.replace(F("{p}"), String(1883)); - } - html.replace(F("{i}"), mqtt.clientId); - html.replace(F("{t}"), mqtt.publishTopic); - html.replace(F("{st}"), mqtt.subscribeTopic); - html.replace(F("{u}"), mqtt.username); - html.replace(F("{pw}"), mqtt.password); - html.replace(F("{f}"), String(mqtt.payloadFormat)); - for(int i = 0; i<5; i++) { - html.replace("{f" + String(i) + "}", mqtt.payloadFormat == i ? F("selected") : F("")); - } - html.replace(F("{f255}"), mqtt.payloadFormat == 255 ? F("selected") : F("")); - - html.replace(F("{s}"), mqtt.ssl ? F("checked") : F("")); - - if(LittleFS.begin()) { - html.replace(F("{dcu}"), LittleFS.exists(FILE_MQTT_CA) ? F("none") : F("")); - html.replace(F("{dcf}"), LittleFS.exists(FILE_MQTT_CA) ? F("") : F("none")); - html.replace(F("{deu}"), LittleFS.exists(FILE_MQTT_CERT) ? F("none") : F("")); - html.replace(F("{def}"), LittleFS.exists(FILE_MQTT_CERT) ? F("") : F("none")); - html.replace(F("{dku}"), LittleFS.exists(FILE_MQTT_KEY) ? F("none") : F("")); - html.replace(F("{dkf}"), LittleFS.exists(FILE_MQTT_KEY) ? F("") : F("none")); - LittleFS.end(); - } else { - html.replace(F("{dcu}"), F("")); - html.replace(F("{dcf}"), F("none")); - html.replace(F("{deu}"), F("")); - html.replace(F("{def}"), F("none")); - html.replace(F("{dku}"), F("")); - html.replace(F("{dkf}"), F("none")); - } - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configDomoticzHtml() { - printD(F("Serving /domoticz.html over http...")); - - if(!checkSecurity(1)) - return; - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - DomoticzConfig domo; - config->getDomoticzConfig(domo); - snprintf_P(buf, BufferSize, DOMOTICZ_HTML, - domo.elidx, - domo.cl1idx, - domo.vl1idx, - domo.vl2idx, - domo.vl3idx - ); - - server.setContentLength(strlen(buf) + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(buf); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configPriceApiHtml() { - printD(F("Serving /priceapi.html over http...")); - - if(!checkSecurity(1)) - return; - - EntsoeConfig entsoe; - config->getEntsoeConfig(entsoe); - - String html = String((const __FlashStringHelper*) PRICEAPI_HTML); - - if(ESP.getFreeHeap() > 32000) { - html.replace("{et}", entsoe.token); - html.replace("{dt}", ""); - } else { - html.replace("{et}", ""); - html.replace("{dt}", "d-none"); - } - html.replace("{em}", String(entsoe.multiplier / 1000.0, 3)); - - html.replace(F("{no1}"), strcmp(entsoe.area, "10YNO-1--------2") == 0 ? "selected" : ""); - html.replace(F("{no2}"), strcmp(entsoe.area, "10YNO-2--------T") == 0 ? "selected" : ""); - html.replace(F("{no3}"), strcmp(entsoe.area, "10YNO-3--------J") == 0 ? "selected" : ""); - html.replace(F("{no4}"), strcmp(entsoe.area, "10YNO-4--------9") == 0 ? "selected" : ""); - html.replace(F("{no5}"), strcmp(entsoe.area, "10Y1001A1001A48H") == 0 ? "selected" : ""); - - html.replace(F("{se1}"), strcmp(entsoe.area, "10Y1001A1001A44P") == 0 ? "selected" : ""); - html.replace(F("{se2}"), strcmp(entsoe.area, "10Y1001A1001A45N") == 0 ? "selected" : ""); - html.replace(F("{se3}"), strcmp(entsoe.area, "10Y1001A1001A46L") == 0 ? "selected" : ""); - html.replace(F("{se4}"), strcmp(entsoe.area, "10Y1001A1001A47J") == 0 ? "selected" : ""); - - html.replace(F("{dk1}"), strcmp(entsoe.area, "10YDK-1--------W") == 0 ? "selected" : ""); - html.replace(F("{dk2}"), strcmp(entsoe.area, "10YDK-2--------M") == 0 ? "selected" : ""); - - html.replace(F("{at}"), strcmp(entsoe.area, "10YAT-APG------L") == 0 ? F("selected") : F("")); - html.replace(F("{be}"), strcmp(entsoe.area, "10YBE----------2") == 0 ? F("selected") : F("")); - html.replace(F("{cz}"), strcmp(entsoe.area, "10YCZ-CEPS-----N") == 0 ? F("selected") : F("")); - html.replace(F("{ee}"), strcmp(entsoe.area, "10Y1001A1001A39I") == 0 ? F("selected") : F("")); - html.replace(F("{fi}"), strcmp(entsoe.area, "10YFI-1--------U") == 0 ? F("selected") : F("")); - html.replace(F("{fr}"), strcmp(entsoe.area, "10YFR-RTE------C") == 0 ? F("selected") : F("")); - html.replace(F("{de}"), strcmp(entsoe.area, "10Y1001A1001A83F") == 0 ? F("selected") : F("")); - html.replace(F("{gb}"), strcmp(entsoe.area, "10YGB----------A") == 0 ? F("selected") : F("")); - html.replace(F("{lv}"), strcmp(entsoe.area, "10YLV-1001A00074") == 0 ? F("selected") : F("")); - html.replace(F("{lt}"), strcmp(entsoe.area, "10YLT-1001A0008Q") == 0 ? F("selected") : F("")); - html.replace(F("{nl}"), strcmp(entsoe.area, "10YNL----------L") == 0 ? F("selected") : F("")); - html.replace(F("{pl}"), strcmp(entsoe.area, "10YPL-AREA-----S") == 0 ? F("selected") : F("")); - html.replace(F("{ch}"), strcmp(entsoe.area, "10YCH-SWISSGRIDZ") == 0 ? F("selected") : F("")); - - html.replace(F("{nok}"), strcmp(entsoe.currency, "NOK") == 0 ? "selected" : ""); - html.replace(F("{sek}"), strcmp(entsoe.currency, "SEK") == 0 ? "selected" : ""); - html.replace(F("{dkk}"), strcmp(entsoe.currency, "DKK") == 0 ? "selected" : ""); - html.replace(F("{eur}"), strcmp(entsoe.currency, "EUR") == 0 ? "selected" : ""); - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configThresholdsHtml() { - printD(F("Serving /thresholds.html over http...")); - - if(!checkSecurity(1)) - return; - - EnergyAccountingConfig* config = ea->getConfig(); - - String html = String((const __FlashStringHelper*) THRESHOLDS_HTML); - for(int i = 0; i < 9; i++) { - html.replace("{t" + String(i) + "}", String(config->thresholds[i], 10)); - } - html.replace(F("{h}"), String(config->hours, 10)); - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configWebHtml() { - printD(F("Serving /web.html over http...")); - - if(!checkSecurity(1)) - return; - - snprintf_P(buf, BufferSize, WEB_HTML, - (char*) (webConfig.security == 0 ? F("selected") : F("")), - (char*) (webConfig.security == 1 ? F("selected") : F("")), - (char*) (webConfig.security == 2 ? F("selected") : F("")), - webConfig.username, - webConfig.password - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf) + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(buf); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::bootCss() { - printD(F("Serving /boot.css over http...")); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); - server.send_P(200, "text/css", BOOT_CSS); -} - -void AmsWebServer::githubSvg() { - printD(F("Serving /github.svg over http...")); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); - server.send_P(200, PSTR("image/svg+xml"), GITHUB_SVG); -} - -void AmsWebServer::dataJson() { - printD(F("Serving /data.json over http...")); - uint64_t now = millis64(); - - if(!checkSecurity(2)) - return; - - float vcc = hw->getVcc(); - int rssi = hw->getWifiRssi(); - - uint8_t espStatus; - #if defined(ESP8266) - if(vcc == 0) { - espStatus = 1; - } else if(vcc > 3.1 && vcc < 3.5) { - espStatus = 1; - } else if(vcc > 3.0 && vcc < 3.6) { - espStatus = 2; - } else { - espStatus = 3; - } - #elif defined(ESP32) - if(vcc == 0) { - espStatus = 1; - } else if(vcc > 2.8 && vcc < 3.5) { - espStatus = 1; - } else if(vcc > 2.7 && vcc < 3.6) { - espStatus = 2; - } else { - espStatus = 3; - } - #endif - - - uint8_t hanStatus; - if(meterConfig->baud == 0) { - hanStatus = 0; - } else if(now - meterState->getLastUpdateMillis() < 15000) { - hanStatus = 1; - } else if(now - meterState->getLastUpdateMillis() < 30000) { - hanStatus = 2; - } else { - hanStatus = 3; - } - - uint8_t wifiStatus; - if(rssi > -75) { - wifiStatus = 1; - } else if(rssi > -95) { - wifiStatus = 2; - } else { - wifiStatus = 3; - } - - uint8_t mqttStatus; - if(!mqttEnabled) { - mqttStatus = 0; - } else if(mqtt != NULL && mqtt->connected()) { - mqttStatus = 1; - } else if(mqtt != NULL && mqtt->lastError() == 0) { - mqttStatus = 2; - } else { - mqttStatus = 3; - } - - float price = ENTSOE_NO_VALUE; - if(eapi != NULL) - price = eapi->getValueForHour(0); - - String peaks = ""; - uint8_t peakCount = ea->getConfig()->hours; - if(peakCount > 5) peakCount = 5; - for(uint8_t i = 1; i <= peakCount; i++) { - if(!peaks.isEmpty()) peaks += ","; - peaks += String(ea->getPeak(i).value / 100.0); - } - - snprintf_P(buf, BufferSize, DATA_JSON, - maxPwr == 0 ? meterState->isThreePhase() ? 20000 : 10000 : maxPwr, - meterConfig->productionCapacity, - meterConfig->mainFuse == 0 ? 32 : meterConfig->mainFuse, - meterState->getActiveImportPower(), - meterState->getActiveExportPower(), - meterState->getReactiveImportPower(), - meterState->getReactiveExportPower(), - meterState->getActiveImportCounter(), - meterState->getActiveExportCounter(), - meterState->getReactiveImportCounter(), - meterState->getReactiveExportCounter(), - meterState->getL1Voltage(), - meterState->getL2Voltage(), - meterState->getL3Voltage(), - meterState->getL1Current(), - meterState->getL2Current(), - meterState->getL3Current(), - meterState->getPowerFactor(), - meterState->getL1PowerFactor(), - meterState->getL2PowerFactor(), - meterState->getL3PowerFactor(), - vcc, - rssi, - hw->getTemperature(), - (uint32_t) (now / 1000), - ESP.getFreeHeap(), - espStatus, - hanStatus, - wifiStatus, - mqttStatus, - mqtt == NULL ? 0 : (int) mqtt->lastError(), - price == ENTSOE_NO_VALUE ? PSTR("null") : String(price, 2).c_str(), - meterState->getMeterType(), - meterConfig->distributionSystem, - ea->getMonthMax(), - peaks.c_str(), - ea->getCurrentThreshold(), - ea->getUseThisHour(), - ea->getCostThisHour(), - ea->getProducedThisHour(), - ea->getIncomeThisHour(), - ea->getUseToday(), - ea->getCostToday(), - ea->getProducedToday(), - ea->getIncomeToday(), - ea->getUseThisMonth(), - ea->getCostThisMonth(), - ea->getProducedThisMonth(), - ea->getIncomeThisMonth(), - (uint32_t) time(nullptr) - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf)); - server.send(200, MIME_JSON, buf); -} - -void AmsWebServer::dayplotJson() { - printD(F("Serving /dayplot.json over http...")); - - if(!checkSecurity(2)) - return; - - if(ds == NULL) { - notFound(); - } else { - snprintf_P(buf, BufferSize, DAYPLOT_JSON, - ds->getHourImport(0) / 1000.0, - ds->getHourImport(1) / 1000.0, - ds->getHourImport(2) / 1000.0, - ds->getHourImport(3) / 1000.0, - ds->getHourImport(4) / 1000.0, - ds->getHourImport(5) / 1000.0, - ds->getHourImport(6) / 1000.0, - ds->getHourImport(7) / 1000.0, - ds->getHourImport(8) / 1000.0, - ds->getHourImport(9) / 1000.0, - ds->getHourImport(10) / 1000.0, - ds->getHourImport(11) / 1000.0, - ds->getHourImport(12) / 1000.0, - ds->getHourImport(13) / 1000.0, - ds->getHourImport(14) / 1000.0, - ds->getHourImport(15) / 1000.0, - ds->getHourImport(16) / 1000.0, - ds->getHourImport(17) / 1000.0, - ds->getHourImport(18) / 1000.0, - ds->getHourImport(19) / 1000.0, - ds->getHourImport(20) / 1000.0, - ds->getHourImport(21) / 1000.0, - ds->getHourImport(22) / 1000.0, - ds->getHourImport(23) / 1000.0, - ds->getHourExport(0) / 1000.0, - ds->getHourExport(1) / 1000.0, - ds->getHourExport(2) / 1000.0, - ds->getHourExport(3) / 1000.0, - ds->getHourExport(4) / 1000.0, - ds->getHourExport(5) / 1000.0, - ds->getHourExport(6) / 1000.0, - ds->getHourExport(7) / 1000.0, - ds->getHourExport(8) / 1000.0, - ds->getHourExport(9) / 1000.0, - ds->getHourExport(10) / 1000.0, - ds->getHourExport(11) / 1000.0, - ds->getHourExport(12) / 1000.0, - ds->getHourExport(13) / 1000.0, - ds->getHourExport(14) / 1000.0, - ds->getHourExport(15) / 1000.0, - ds->getHourExport(16) / 1000.0, - ds->getHourExport(17) / 1000.0, - ds->getHourExport(18) / 1000.0, - ds->getHourExport(19) / 1000.0, - ds->getHourExport(20) / 1000.0, - ds->getHourExport(21) / 1000.0, - ds->getHourExport(22) / 1000.0, - ds->getHourExport(23) / 1000.0 - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf)); - server.send(200, MIME_JSON, buf); - } -} - -void AmsWebServer::monthplotJson() { - printD(F("Serving /monthplot.json over http...")); - - if(!checkSecurity(2)) - return; - - if(ds == NULL) { - notFound(); - } else { - snprintf_P(buf, BufferSize, MONTHPLOT_JSON, - ds->getDayImport(1) / 1000.0, - ds->getDayImport(2) / 1000.0, - ds->getDayImport(3) / 1000.0, - ds->getDayImport(4) / 1000.0, - ds->getDayImport(5) / 1000.0, - ds->getDayImport(6) / 1000.0, - ds->getDayImport(7) / 1000.0, - ds->getDayImport(8) / 1000.0, - ds->getDayImport(9) / 1000.0, - ds->getDayImport(10) / 1000.0, - ds->getDayImport(11) / 1000.0, - ds->getDayImport(12) / 1000.0, - ds->getDayImport(13) / 1000.0, - ds->getDayImport(14) / 1000.0, - ds->getDayImport(15) / 1000.0, - ds->getDayImport(16) / 1000.0, - ds->getDayImport(17) / 1000.0, - ds->getDayImport(18) / 1000.0, - ds->getDayImport(19) / 1000.0, - ds->getDayImport(20) / 1000.0, - ds->getDayImport(21) / 1000.0, - ds->getDayImport(22) / 1000.0, - ds->getDayImport(23) / 1000.0, - ds->getDayImport(24) / 1000.0, - ds->getDayImport(25) / 1000.0, - ds->getDayImport(26) / 1000.0, - ds->getDayImport(27) / 1000.0, - ds->getDayImport(28) / 1000.0, - ds->getDayImport(29) / 1000.0, - ds->getDayImport(30) / 1000.0, - ds->getDayImport(31) / 1000.0, - ds->getDayExport(1) / 1000.0, - ds->getDayExport(2) / 1000.0, - ds->getDayExport(3) / 1000.0, - ds->getDayExport(4) / 1000.0, - ds->getDayExport(5) / 1000.0, - ds->getDayExport(6) / 1000.0, - ds->getDayExport(7) / 1000.0, - ds->getDayExport(8) / 1000.0, - ds->getDayExport(9) / 1000.0, - ds->getDayExport(10) / 1000.0, - ds->getDayExport(11) / 1000.0, - ds->getDayExport(12) / 1000.0, - ds->getDayExport(13) / 1000.0, - ds->getDayExport(14) / 1000.0, - ds->getDayExport(15) / 1000.0, - ds->getDayExport(16) / 1000.0, - ds->getDayExport(17) / 1000.0, - ds->getDayExport(18) / 1000.0, - ds->getDayExport(19) / 1000.0, - ds->getDayExport(20) / 1000.0, - ds->getDayExport(21) / 1000.0, - ds->getDayExport(22) / 1000.0, - ds->getDayExport(23) / 1000.0, - ds->getDayExport(24) / 1000.0, - ds->getDayExport(25) / 1000.0, - ds->getDayExport(26) / 1000.0, - ds->getDayExport(27) / 1000.0, - ds->getDayExport(28) / 1000.0, - ds->getDayExport(29) / 1000.0, - ds->getDayExport(30) / 1000.0, - ds->getDayExport(31) / 1000.0 - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf)); - server.send(200, MIME_JSON, buf); - } -} - -void AmsWebServer::energyPriceJson() { - printD(F("Serving /energyprice.json over http...")); - - if(!checkSecurity(2)) - return; - - float prices[36]; - for(int i = 0; i < 36; i++) { - prices[i] = eapi == NULL ? ENTSOE_NO_VALUE : eapi->getValueForHour(i); - } - - snprintf_P(buf, BufferSize, ENERGYPRICE_JSON, - eapi == NULL ? "" : eapi->getCurrency(), - prices[0] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[0], 4).c_str(), - prices[1] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[1], 4).c_str(), - prices[2] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[2], 4).c_str(), - prices[3] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[3], 4).c_str(), - prices[4] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[4], 4).c_str(), - prices[5] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[5], 4).c_str(), - prices[6] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[6], 4).c_str(), - prices[7] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[7], 4).c_str(), - prices[8] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[8], 4).c_str(), - prices[9] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[9], 4).c_str(), - prices[10] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[10], 4).c_str(), - prices[11] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[11], 4).c_str(), - prices[12] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[12], 4).c_str(), - prices[13] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[13], 4).c_str(), - prices[14] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[14], 4).c_str(), - prices[15] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[15], 4).c_str(), - prices[16] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[16], 4).c_str(), - prices[17] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[17], 4).c_str(), - prices[18] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[18], 4).c_str(), - prices[19] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[19], 4).c_str(), - prices[20] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[20], 4).c_str(), - prices[21] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[21], 4).c_str(), - prices[22] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[22], 4).c_str(), - prices[23] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[23], 4).c_str(), - prices[24] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[24], 4).c_str(), - prices[25] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[25], 4).c_str(), - prices[26] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[26], 4).c_str(), - prices[27] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[27], 4).c_str(), - prices[28] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[28], 4).c_str(), - prices[29] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[29], 4).c_str(), - prices[30] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[30], 4).c_str(), - prices[31] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[31], 4).c_str(), - prices[32] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[32], 4).c_str(), - prices[33] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[33], 4).c_str(), - prices[34] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[34], 4).c_str(), - prices[35] == ENTSOE_NO_VALUE ? PSTR("null") : String(prices[35], 4).c_str() - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf)); - server.send(200, MIME_JSON, buf); -} - -void AmsWebServer::handleSetup() { - printD(F("Handling setup method from http")); - - if(!server.hasArg(F("wifiSsid")) || server.arg(F("wifiSsid")).isEmpty() || !server.hasArg(F("wifiPassword")) || server.arg(F("wifiPassword")).isEmpty()) { - server.sendHeader(HEADER_LOCATION, F("/"), true); - server.send (302, MIME_PLAIN, F("")); - } else { - SystemConfig sys { static_cast(server.arg(F("board")).toInt()) }; - - DebugConfig debugConfig; - config->getDebugConfig(debugConfig); - config->clear(); - - WiFiConfig wifi; - config->clearWifi(wifi); - - switch(sys.boardType) { - case 0: // roarfred - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 3; - gpioConfig->apPin = 0; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - gpioConfig->tempSensorPin = 5; - break; - case 1: // Arnio Kamstrup - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 3; - gpioConfig->apPin = 0; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - gpioConfig->ledPinRed = 13; - gpioConfig->ledPinGreen = 14; - gpioConfig->ledRgbInverted = true; - break; - case 2: // spenceme - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 3; - gpioConfig->apPin = 0; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - gpioConfig->tempSensorPin = 5; - gpioConfig->vccBootLimit = 33; - wifi.sleep = 1; - break; - case 3: // Pow UART0 - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 3; - gpioConfig->apPin = 0; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - gpioConfig->ledPinRed = 13; - gpioConfig->ledPinGreen = 14; - gpioConfig->ledRgbInverted = true; - wifi.sleep = 1; - break; - case 4: // Pow GPIO12 - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 12; - gpioConfig->apPin = 0; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - gpioConfig->ledPinRed = 13; - gpioConfig->ledPinGreen = 14; - gpioConfig->ledRgbInverted = true; - wifi.sleep = 1; - break; - case 5: // Pow-K+ UART2 - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 16; - gpioConfig->apPin = 0; - gpioConfig->ledPinRed = 13; - gpioConfig->ledPinGreen = 14; - gpioConfig->ledRgbInverted = true; - gpioConfig->vccPin = 10; - gpioConfig->vccResistorGnd = 22; - gpioConfig->vccResistorVcc = 33; - wifi.sleep = 1; - break; - case 6: // Pow-P1 - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 16; - gpioConfig->apPin = 0; - gpioConfig->ledPinRed = 13; - gpioConfig->ledPinGreen = 14; - gpioConfig->ledRgbInverted = true; - gpioConfig->vccPin = 10; - gpioConfig->vccResistorGnd = 22; - gpioConfig->vccResistorVcc = 33; - break; - case 7: // Pow-U+ - config->clearGpio(*gpioConfig); - gpioConfig->hanPin = 16; - gpioConfig->apPin = 0; - gpioConfig->ledPinRed = 13; - gpioConfig->ledPinGreen = 14; - gpioConfig->ledRgbInverted = true; - gpioConfig->vccPin = 10; - gpioConfig->vccResistorGnd = 22; - gpioConfig->vccResistorVcc = 33; - wifi.sleep = 2; - break; - case 101: // D1 - gpioConfig->hanPin = 5; - gpioConfig->apPin = 4; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - gpioConfig->vccMultiplier = 1100; - break; - case 100: // ESP8266 - gpioConfig->hanPin = 3; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = true; - break; - case 201: // D32 - gpioConfig->hanPin = 16; - gpioConfig->apPin = 4; - gpioConfig->ledPin = 5; - gpioConfig->ledInverted = true; - break; - case 202: // Feather - gpioConfig->hanPin = 16; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = false; - break; - case 203: // DevKitC - gpioConfig->hanPin = 16; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = false; - break; - case 200: // ESP32 - gpioConfig->hanPin = 16; - gpioConfig->ledPin = 2; - gpioConfig->ledInverted = false; - break; - case 50: // S2 - gpioConfig->hanPin = 18; - wifi.sleep = 1; - break; - case 51: // S2-mini - gpioConfig->hanPin = 18; - gpioConfig->ledPin = 15; - gpioConfig->ledInverted = false; - gpioConfig->apPin = 0; - wifi.sleep = 1; - break; - } - - strcpy(wifi.ssid, server.arg(F("wifiSsid")).c_str()); - strcpy(wifi.psk, server.arg(F("wifiPassword")).c_str()); - - if(server.hasArg(F("wifiIpType")) && server.arg(F("wifiIpType")).toInt() == 1) { - strcpy(wifi.ip, server.arg(F("wifiIp")).c_str()); - strcpy(wifi.gateway, server.arg(F("wifiGw")).c_str()); - strcpy(wifi.subnet, server.arg(F("wifiSubnet")).c_str()); - strcpy(wifi.dns1, server.arg(F("wifiDns1")).c_str()); - } - if(server.hasArg(F("wifiHostname")) && !server.arg(F("wifiHostname")).isEmpty()) { - strcpy(wifi.hostname, server.arg(F("wifiHostname")).c_str()); - wifi.mdns = true; - } else { - wifi.mdns = false; - } - - MqttConfig mqttConfig; - config->clearMqtt(mqttConfig); - - config->clearAuth(webConfig); - - NtpConfig ntp; - config->clearNtp(ntp); - - bool success = true; - if(!config->setSystemConfig(sys)) { - printD(F("Unable to set system config")); - success = false; - } - if(!config->setWiFiConfig(wifi)) { - printD(F("Unable to set WiFi config")); - success = false; - } - if(!config->setMqttConfig(mqttConfig)) { - printD(F("Unable to set MQTT config")); - success = false; - } - if(!config->setWebConfig(webConfig)) { - printD(F("Unable to set web config")); - success = false; - } - if(!config->setGpioConfig(*gpioConfig)) { - printD(F("Unable to set GPIO config")); - success = false; - } - if(!config->setNtpConfig(ntp)) { - printD(F("Unable to set NTP config")); - success = false; - } - - config->setDebugConfig(debugConfig); - - if(success && config->save()) { - performRestart = true; - server.sendHeader(HEADER_LOCATION,"/restart-wait"); - server.send(303); - } else { - printE(F("Error saving configuration")); - server.send_P(500, MIME_HTML, PSTR("

Error saving configuration!

")); - } - } -} - -void AmsWebServer::handleSave() { - printD(F("Handling save method from http")); - if(!checkSecurity(1)) - return; - - if(server.hasArg(F("mc")) && server.arg(F("mc")) == F("true")) { - printD(F("Received meter config")); - config->getMeterConfig(*meterConfig); - meterConfig->baud = server.arg(F("b")).toInt(); - meterConfig->parity = server.arg(F("c")).toInt(); - meterConfig->invert = server.hasArg(F("i")) && server.arg(F("i")) == F("true"); - meterConfig->distributionSystem = server.arg(F("d")).toInt(); - meterConfig->mainFuse = server.arg(F("f")).toInt(); - meterConfig->productionCapacity = server.arg(F("p")).toInt(); - maxPwr = 0; - - String encryptionKeyHex = server.arg(F("e")); - if(!encryptionKeyHex.isEmpty()) { - encryptionKeyHex.replace(F("0x"), F("")); - fromHex(meterConfig->encryptionKey, encryptionKeyHex, 16); - } - - String authenticationKeyHex = server.arg(F("a")); - if(!authenticationKeyHex.isEmpty()) { - authenticationKeyHex.replace(F("0x"), F("")); - fromHex(meterConfig->authenticationKey, authenticationKeyHex, 16); - } - config->setMeterConfig(*meterConfig); - } - - if(server.hasArg(F("ma")) && server.arg(F("ma")) == F("true")) { - printD(F("Received meter advanced config")); - config->getMeterConfig(*meterConfig); - meterConfig->wattageMultiplier = server.arg(F("wm")).toDouble() * 1000; - meterConfig->voltageMultiplier = server.arg(F("vm")).toDouble() * 1000; - meterConfig->amperageMultiplier = server.arg(F("am")).toDouble() * 1000; - meterConfig->accumulatedMultiplier = server.arg(F("cm")).toDouble() * 1000; - config->setMeterConfig(*meterConfig); - } - - if(server.hasArg(F("wc")) && server.arg(F("wc")) == F("true")) { - printD(F("Received WiFi config")); - WiFiConfig wifi; - config->clearWifi(wifi); - strcpy(wifi.ssid, server.arg(F("s")).c_str()); - strcpy(wifi.psk, server.arg(F("p")).c_str()); - - if(server.hasArg(F("st")) && server.arg(F("st")).toInt() == 1) { - strcpy(wifi.ip, server.arg(F("i")).c_str()); - strcpy(wifi.gateway, server.arg(F("g")).c_str()); - strcpy(wifi.subnet, server.arg(F("sn")).c_str()); - strcpy(wifi.dns1, server.arg(F("d1")).c_str()); - strcpy(wifi.dns2, server.arg(F("d2")).c_str()); - } - if(server.hasArg(F("h")) && !server.arg(F("h")).isEmpty()) { - strcpy(wifi.hostname, server.arg(F("h")).c_str()); - } - wifi.mdns = server.arg(F("m")) == F("true"); - wifi.power = server.arg(F("w")).toFloat() * 10; - wifi.sleep = server.arg(F("z")).toInt(); - config->setWiFiConfig(wifi); - } - - if(server.hasArg(F("mqc")) && server.arg(F("mqc")) == F("true")) { - printD(F("Received MQTT config")); - MqttConfig mqtt; - if(server.hasArg(F("m")) && server.arg(F("m")) == F("true")) { - strcpy(mqtt.host, server.arg(F("h")).c_str()); - strcpy(mqtt.clientId, server.arg(F("i")).c_str()); - strcpy(mqtt.publishTopic, server.arg(F("t")).c_str()); - strcpy(mqtt.subscribeTopic, server.arg(F("st")).c_str()); - strcpy(mqtt.username, server.arg(F("u")).c_str()); - strcpy(mqtt.password, server.arg(F("pw")).c_str()); - mqtt.payloadFormat = server.arg(F("f")).toInt(); - mqtt.ssl = server.arg(F("s")) == F("true"); - - mqtt.port = server.arg(F("p")).toInt(); - if(mqtt.port == 0) { - mqtt.port = mqtt.ssl ? 8883 : 1883; - } - } else { - config->clearMqtt(mqtt); - } - config->setMqttConfig(mqtt); - } - - if(server.hasArg(F("dc")) && server.arg(F("dc")) == F("true")) { - printD(F("Received Domoticz config")); - DomoticzConfig domo { - static_cast(server.arg(F("elidx")).toInt()), - static_cast(server.arg(F("vl1idx")).toInt()), - static_cast(server.arg(F("vl2idx")).toInt()), - static_cast(server.arg(F("vl3idx")).toInt()), - static_cast(server.arg(F("cl1idx")).toInt()) - }; - config->setDomoticzConfig(domo); - } - - - if(server.hasArg(F("ac")) && server.arg(F("ac")) == F("true")) { - printD(F("Received web config")); - webConfig.security = server.arg(F("as")).toInt(); - if(webConfig.security > 0) { - strcpy(webConfig.username, server.arg(F("au")).c_str()); - strcpy(webConfig.password, server.arg(F("ap")).c_str()); - debugger->setPassword(webConfig.password); - } else { - strcpy_P(webConfig.username, PSTR("")); - strcpy_P(webConfig.password, PSTR("")); - debugger->setPassword(F("")); - } - config->setWebConfig(webConfig); - } - - if(server.hasArg(F("gc")) && server.arg(F("gc")) == F("true")) { - printD(F("Received GPIO config")); - gpioConfig->hanPin = server.hasArg(F("h")) && !server.arg(F("h")).isEmpty() ? server.arg(F("h")).toInt() : 3; - gpioConfig->ledPin = server.hasArg(F("l")) && !server.arg(F("l")).isEmpty() ? server.arg(F("l")).toInt() : 0xFF; - gpioConfig->ledInverted = server.hasArg(F("i")) && server.arg(F("i")) == F("true"); - gpioConfig->ledPinRed = server.hasArg(F("r")) && !server.arg(F("r")).isEmpty() ? server.arg(F("r")).toInt() : 0xFF; - gpioConfig->ledPinGreen = server.hasArg(F("e")) && !server.arg(F("e")).isEmpty() ? server.arg(F("e")).toInt() : 0xFF; - gpioConfig->ledPinBlue = server.hasArg(F("b")) && !server.arg(F("b")).isEmpty() ? server.arg(F("b")).toInt() : 0xFF; - gpioConfig->ledRgbInverted = server.hasArg(F("n")) && server.arg(F("n")) == F("true"); - gpioConfig->apPin = server.hasArg(F("a")) && !server.arg(F("a")).isEmpty() ? server.arg(F("a")).toInt() : 0xFF; - gpioConfig->tempSensorPin = server.hasArg(F("t")) && !server.arg(F("t")).isEmpty() ?server.arg(F("t")).toInt() : 0xFF; - gpioConfig->tempAnalogSensorPin = server.hasArg(F("m")) && !server.arg(F("m")).isEmpty() ?server.arg(F("m")).toInt() : 0xFF; - gpioConfig->vccPin = server.hasArg(F("v")) && !server.arg(F("v")).isEmpty() ? server.arg(F("v")).toInt() : 0xFF; - gpioConfig->vccOffset = server.hasArg(F("o")) && !server.arg(F("o")).isEmpty() ? server.arg(F("o")).toFloat() * 100 : 0; - gpioConfig->vccMultiplier = server.hasArg(F("u")) && !server.arg(F("u")).isEmpty() ? server.arg(F("u")).toFloat() * 1000 : 1000; - gpioConfig->vccBootLimit = server.hasArg(F("c")) && !server.arg(F("c")).isEmpty() ? server.arg(F("c")).toFloat() * 10 : 0; - gpioConfig->vccResistorGnd = server.hasArg(F("d")) && !server.arg(F("d")).isEmpty() ? server.arg(F("d")).toInt() : 0; - gpioConfig->vccResistorVcc = server.hasArg(F("s")) && !server.arg(F("s")).isEmpty() ? server.arg(F("s")).toInt() : 0; - config->setGpioConfig(*gpioConfig); - } - - if(server.hasArg(F("debugConfig")) && server.arg(F("debugConfig")) == F("true")) { - printD(F("Received Debug config")); - DebugConfig debug; - config->getDebugConfig(debug); - bool active = debug.serial || debug.telnet; - - debug.telnet = server.hasArg(F("debugTelnet")) && server.arg(F("debugTelnet")) == F("true"); - debug.serial = server.hasArg(F("debugSerial")) && server.arg(F("debugSerial")) == F("true"); - debug.level = server.arg(F("debugLevel")).toInt(); - - if(debug.telnet || debug.serial) { - if(webConfig.security > 0) { - debugger->setPassword(webConfig.password); - } else { - debugger->setPassword(F("")); - } - debugger->setSerialEnabled(debug.serial); - WiFiConfig wifi; - if(config->getWiFiConfig(wifi) && strlen(wifi.hostname) > 0) { - debugger->begin(wifi.hostname, (uint8_t) debug.level); - if(!debug.telnet) { - debugger->stop(); - } - } - } else if(active) { - performRestart = true; - } - config->setDebugConfig(debug); - } - - if(server.hasArg(F("nc")) && server.arg(F("nc")) == F("true")) { - printD(F("Received NTP config")); - NtpConfig ntp { - server.hasArg(F("n")) && server.arg(F("n")) == F("true"), - server.hasArg(F("nd")) && server.arg(F("nd")) == F("true"), - static_cast(server.arg(F("o")).toInt() / 10), - static_cast(server.arg(F("so")).toInt() / 10) - }; - strcpy(ntp.server, server.arg(F("ns")).c_str()); - config->setNtpConfig(ntp); - } - - if(server.hasArg(F("ec")) && server.arg(F("ec")) == F("true")) { - printD(F("Received ENTSO-E config")); - EntsoeConfig entsoe; - strcpy(entsoe.token, server.arg(F("et")).c_str()); - strcpy(entsoe.area, server.arg(F("ea")).c_str()); - strcpy(entsoe.currency, server.arg(F("ecu")).c_str()); - entsoe.multiplier = server.arg(F("em")).toFloat() * 1000; - config->setEntsoeConfig(entsoe); - } - - if(server.hasArg(F("cc")) && server.arg(F("cc")) == F("true")) { - printD(F("Received energy accounting config")); - EnergyAccountingConfig eac; - eac.thresholds[0] = server.arg(F("t0")).toInt(); - eac.thresholds[1] = server.arg(F("t1")).toInt(); - eac.thresholds[2] = server.arg(F("t2")).toInt(); - eac.thresholds[3] = server.arg(F("t3")).toInt(); - eac.thresholds[4] = server.arg(F("t4")).toInt(); - eac.thresholds[5] = server.arg(F("t5")).toInt(); - eac.thresholds[6] = server.arg(F("t6")).toInt(); - eac.thresholds[7] = server.arg(F("t7")).toInt(); - eac.thresholds[8] = server.arg(F("t8")).toInt(); - eac.hours = server.arg(F("h")).toInt(); - config->setEnergyAccountingConfig(eac); - } - - printI(F("Saving configuration now...")); - - //if (debugger->isActive(RemoteDebug::DEBUG)) config->print(debugger); - if (config->save()) { - printI(F("Successfully saved.")); - if(config->isWifiChanged() || performRestart) { - performRestart = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); - } else { - server.sendHeader(HEADER_LOCATION, F("/"), true); - server.send_P(302, MIME_PLAIN, PSTR("")); - - hw->setup(gpioConfig, config); - } - } else { - printE(F("Error saving configuration")); - server.send_P(500, MIME_HTML, PSTR("

Error saving configuration!

")); - } -} - -void AmsWebServer::configNtpHtml() { - printD(F("Serving /ntp.html over http...")); - - if(!checkSecurity(1)) - return; - - NtpConfig ntp; - config->getNtpConfig(ntp); - snprintf_P(buf, BufferSize, NTP_HTML, - (char*) (ntp.enable ? F("checked") : F("")), - (char*) (ntp.offset == 0 ? F("selected") : F("")), - (char*) (ntp.offset == 360 ? F("selected") : F("")), - (char*) (ntp.offset == 720 ? F("selected") : F("")), - (char*) (ntp.summerOffset == 0 ? F("selected") : F("")), - (char*) (ntp.summerOffset == 360 ? F("selected") : F("")), - (char*) (ntp.server), - (char*) (ntp.dhcp ? F("checked") : F("")) - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(strlen(buf) + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(buf); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configGpioHtml() { - printD(F("Serving /gpio.html over http...")); - - if(!checkSecurity(1)) - return; - - String html = String((const __FlashStringHelper*) GPIO_HTML); - - #if defined(CONFIG_IDF_TARGET_ESP32S2) - html.replace(F("${g}"), F("44")); - #elif defined(ESP32) - html.replace(F("${g}"), F("39")); - #else - html.replace(F("${g}"), F("16")); - #endif - - html.replace(F("${h}"), getSerialSelectOptions(gpioConfig->hanPin)); - - html.replace(F("${l}"), gpioConfig->ledPin == 0xFF ? "" : String(gpioConfig->ledPin)); - html.replace(F("${i}"), gpioConfig->ledInverted ? F("checked") : F("")); - html.replace(F("${r}"), gpioConfig->ledPinRed == 0xFF ? "" : String(gpioConfig->ledPinRed)); - html.replace(F("${e}"), gpioConfig->ledPinGreen == 0xFF ? "" : String(gpioConfig->ledPinGreen)); - html.replace(F("${b}"), gpioConfig->ledPinBlue == 0xFF ? "" : String(gpioConfig->ledPinBlue)); - html.replace(F("${n}"), gpioConfig->ledRgbInverted ? F("checked") : F("")); - html.replace(F("${a}"), gpioConfig->apPin == 0xFF ? "" : String(gpioConfig->apPin)); - html.replace(F("${t}"), gpioConfig->tempSensorPin == 0xFF ? "" : String(gpioConfig->tempSensorPin)); - html.replace(F("${m}"), gpioConfig->tempAnalogSensorPin == 0xFF ? "" : String(gpioConfig->tempAnalogSensorPin)); - html.replace(F("${v}"), gpioConfig->vccPin == 0xFF ? "" : String(gpioConfig->vccPin)); - - html.replace(F("${o}"), gpioConfig->vccOffset > 0 ? String(gpioConfig->vccOffset / 100.0, 2) : F("")); - html.replace(F("${u}"), gpioConfig->vccMultiplier > 0 ? String(gpioConfig->vccMultiplier / 1000.0, 2) : F("")); - html.replace(F("${c}"), gpioConfig->vccBootLimit > 0 ? String(gpioConfig->vccBootLimit / 10.0, 1) : F("")); - - html.replace(F("${d}"), gpioConfig->vccResistorGnd > 0 ? String(gpioConfig->vccResistorGnd) : F("")); - html.replace(F("${s}"), gpioConfig->vccResistorVcc > 0 ? String(gpioConfig->vccResistorVcc) : F("")); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configDebugHtml() { - printD(F("Serving /debugging.html over http...")); - - if(!checkSecurity(1)) - return; - - DebugConfig debug; - config->getDebugConfig(debug); - snprintf_P(buf, BufferSize, DEBUGGING_HTML, - (char*) (debug.telnet ? F("checked") : F("")), - (char*) (debug.serial ? F("checked") : F("")), - (char*) (debug.level == 1 ? F("selected") : F("")), - (char*) (debug.level == 2 ? F("selected") : F("")), - (char*) (debug.level == 3 ? F("selected") : F("")), - (char*) (debug.level == 4 ? F("selected") : F("")) - ); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - - server.setContentLength(strlen(buf) + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(buf); - server.sendContent_P(FOOT_HTML); -} - -String AmsWebServer::getSerialSelectOptions(int selected) { - String gpioOptions; - if(selected == 3) { - gpioOptions += F(""); - } else { - gpioOptions += F(""); - } - #if defined(CONFIG_IDF_TARGET_ESP32S2) - int numGpio = 30; - int gpios[] = {4,5,6,7,8,9,10,11,12,13,14,15,16,17,19,21,22,23,25,32,33,34,35,36,39,40,41,42,43,44}; - if(selected == 18) { - gpioOptions += F(""); - } else { - gpioOptions += F(""); - } - #elif defined(ESP32) - int numGpio = 24; - int gpios[] = {4,5,6,7,8,10,11,12,13,14,15,17,18,19,21,22,23,25,32,33,34,35,36,39}; - if(selected == 9) { - gpioOptions += F(""); - } else { - gpioOptions += F(""); - } - if(selected == 16) { - gpioOptions += F(""); - } else { - gpioOptions += F(""); - } - #elif defined(ESP8266) - int numGpio = 9; - int gpios[] = {4,5,9,10,12,13,14,15,16}; - if(selected == 113) { - gpioOptions += F(""); - } else { - gpioOptions += F(""); - } - #endif - - for(int i = 0; i < numGpio; i++) { - int gpio = gpios[i]; - char buffer [16]; - sprintf(buffer, "%02u", gpio); - if(gpio == selected) { - gpioOptions += ""; - } else { - gpioOptions += ""; - } - } - return gpioOptions; -} - -void AmsWebServer::uploadPost() { - server.send(200); -} - -HTTPUpload& AmsWebServer::uploadFile(const char* path) { - HTTPUpload& upload = server.upload(); - if(upload.status == UPLOAD_FILE_START){ - if(uploading) { - printE(F("Upload already in progress")); - server.send_P(500, MIME_HTML, PSTR("

Upload already in progress!

")); - } else if (!LittleFS.begin()) { - printE(F("An Error has occurred while mounting LittleFS")); - server.send_P(500, MIME_HTML, PSTR("

Unable to mount LittleFS!

")); - } else { - uploading = true; - if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf_P(PSTR("handleFileUpload file: %s\n"), path); - } - if(LittleFS.exists(path)) { - LittleFS.remove(path); - } - file = LittleFS.open(path, "w"); - if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf_P(PSTR("handleFileUpload Open file and write: %u\n"), upload.currentSize); - } - size_t written = file.write(upload.buf, upload.currentSize); - if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf_P(PSTR("handleFileUpload Written: %u\n"), written); - } - } - } else if(upload.status == UPLOAD_FILE_WRITE) { - if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf_P(PSTR("handleFileUpload Writing: %u\n"), upload.currentSize); - } - if(file) { - size_t written = file.write(upload.buf, upload.currentSize); - if(debugger->isActive(RemoteDebug::DEBUG)) { - debugger->printf_P(PSTR("handleFileUpload Written: %u\n"), written); - } - delay(1); - if(written != upload.currentSize) { - file.flush(); - file.close(); - LittleFS.remove(path); - LittleFS.end(); - - printE(F("An Error has occurred while writing file")); - server.send_P(500, MIME_HTML, PSTR("

Unable to write file!

")); - } - } - } else if(upload.status == UPLOAD_FILE_END) { - if(file) { - file.flush(); - file.close(); -// LittleFS.end(); - } else { - server.send_P(500, MIME_PLAIN, PSTR("500: couldn't create file")); - } - } - return upload; -} - -void AmsWebServer::deleteFile(const char* path) { - if(LittleFS.begin()) { - LittleFS.remove(path); - LittleFS.end(); - } -} - -void AmsWebServer::firmwareHtml() { - printD(F("Serving /firmware.html over http...")); - - if(!checkSecurity(1)) - return; - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - String html = String((const __FlashStringHelper*) FIRMWARE_HTML); - - #if defined(ESP8266) - html.replace(F("{chipset}"), F("ESP8266")); - #elif defined(CONFIG_IDF_TARGET_ESP32S2) - html.replace(F("{chipset}"), F("ESP32S2")); - #elif defined(ESP32) - #if defined(CONFIG_FREERTOS_UNICORE) - html.replace(F("{chipset}"), F("ESP32SOLO")); - #else - html.replace(F("{chipset}"), F("ESP32")); - #endif - #endif - - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::firmwarePost() { - printD(F("Handlling firmware post...")); - if(!checkSecurity(1)) - return; - - if(rebootForUpgrade) { - server.send(200); - } else { - if(server.hasArg(F("url"))) { - String url = server.arg(F("url")); - if(!url.isEmpty() && (url.startsWith(F("http://")) || url.startsWith(F("https://")))) { - printD(F("Custom firmware URL was provided")); - customFirmwareUrl = url; - performUpgrade = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); - return; - } - } - server.sendHeader(HEADER_LOCATION,F("/firmware")); - server.send(303); - } -} - -void AmsWebServer::firmwareUpload() { - printD(F("Handlling firmware upload...")); - if(!checkSecurity(1)) - return; - - HTTPUpload& upload = server.upload(); - String filename = upload.filename; - if(filename.isEmpty()) return; - - if(upload.status == UPLOAD_FILE_START) { - if(!filename.endsWith(".bin")) { - server.send_P(500, MIME_PLAIN, PSTR("500: couldn't create file")); - } else { - #if defined(ESP32) - esp_task_wdt_delete(NULL); - esp_task_wdt_deinit(); - #elif defined(ESP8266) - ESP.wdtDisable(); - #endif - } - } - uploadFile(FILE_FIRMWARE); - if(upload.status == UPLOAD_FILE_END) { - rebootForUpgrade = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); - } -} - -void AmsWebServer::firmwareDownload() { - if(!checkSecurity(1)) - return; - - printD(F("Firmware download URL triggered")); - performUpgrade = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); -} - -void AmsWebServer::restartHtml() { - printD(F("Serving /restart.html over http...")); - - if(!checkSecurity(1)) - return; - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(RESTART_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent_P(RESTART_HTML); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::restartPost() { - if(!checkSecurity(1)) - return; - - printD(F("Setting restart flag and redirecting")); - performRestart = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); -} - -void AmsWebServer::restartWaitHtml() { - printD(F("Serving /restart-wait.html over http...")); - - if(!checkSecurity(1)) - return; - - String html = String((const __FlashStringHelper*) RESTARTWAIT_HTML); - - WiFiConfig wifi; - config->getWiFiConfig(wifi); - - if(WiFi.getMode() != WIFI_AP) { - html.replace(F("boot.css"), BOOTSTRAP_URL); - } - if(strlen(wifi.ip) == 0 && WiFi.getMode() != WIFI_AP) { - html.replace(F("${ip}"), WiFi.localIP().toString()); - } else { - html.replace(F("${ip}"), wifi.ip); - } - html.replace(F("${hostname}"), wifi.hostname); - - if(performUpgrade || rebootForUpgrade) { - html.replace(F("{rs}"), "d-none"); - html.replace(F("{us}"), F("")); - } else { - html.replace(F("{rs}"), F("")); - html.replace(F("{us}"), "d-none"); - } - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(html.length()); - server.send(200, MIME_HTML, html); - - yield(); - if(performRestart || rebootForUpgrade) { - if(ds != NULL) { - ds->save(); - } - printI(F("Rebooting")); - delay(1000); -#if defined(ESP8266) - ESP.reset(); -#elif defined(ESP32) - ESP.restart(); -#endif - performRestart = false; - } else if(performUpgrade) { - WiFiClient client; - String url = customFirmwareUrl.isEmpty() || !customFirmwareUrl.startsWith(F("http")) ? F("http://hub.amsleser.no/hub/firmware/update") : customFirmwareUrl; - #if defined(ESP8266) - String chipType = F("esp8266"); - #elif defined(CONFIG_IDF_TARGET_ESP32S2) - String chipType = F("esp32s2"); - #elif defined(ESP32) - #if defined(CONFIG_FREERTOS_UNICORE) - String chipType = F("esp32solo"); - #else - String chipType = F("esp32"); - #endif - #endif - - #if defined(ESP8266) - ESPhttpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - t_httpUpdate_return ret = ESPhttpUpdate.update(client, url, VERSION); - #elif defined(ESP32) - HTTPUpdate httpUpdate; - httpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - HTTPUpdateResult ret = httpUpdate.update(client, url, String(VERSION) + "-" + chipType); - #endif - - switch(ret) { - case HTTP_UPDATE_FAILED: - printE(F("Update failed")); - break; - case HTTP_UPDATE_NO_UPDATES: - printI(F("No Update")); - break; - case HTTP_UPDATE_OK: - printI(F("Update OK")); - break; - } - performUpgrade = false; - } -} - -void AmsWebServer::isAliveCheck() { - server.sendHeader(F("Access-Control-Allow-Origin"), F("*")); - server.send(200); -} - -void AmsWebServer::uploadHtml(const char* label, const char* action, const char* menu) { - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(UPLOAD_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent_P(UPLOAD_HTML); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::deleteHtml(const char* label, const char* action, const char* menu) { - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(DELETE_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent_P(DELETE_HTML); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::mqttCa() { - printD(F("Serving /mqtt-ca.html over http...")); - - if(!checkSecurity(1)) - return; - - if(LittleFS.begin()) { - if(LittleFS.exists(FILE_MQTT_CA)) { - deleteHtml("CA file", "/mqtt-ca/delete", "mqtt"); - } else { - uploadHtml("CA file", "/mqtt-ca", "mqtt"); - } - LittleFS.end(); - } else { - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - } -} - -void AmsWebServer::mqttCaUpload() { - if(!checkSecurity(1)) - return; - - uploadFile(FILE_MQTT_CA); - HTTPUpload& upload = server.upload(); - if(upload.status == UPLOAD_FILE_END) { - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - - MqttConfig mqttConfig; - if(config->getMqttConfig(mqttConfig) && mqttConfig.ssl) { - config->setMqttChanged(); - } - } -} - -void AmsWebServer::mqttCaDelete() { - if(!checkSecurity(1)) - return; - - if(!uploading) { // Not an upload - deleteFile(FILE_MQTT_CA); - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - MqttConfig mqttConfig; - if(config->getMqttConfig(mqttConfig) && mqttConfig.ssl) { - config->setMqttChanged(); - } - } else { - uploading = false; - server.send(200); - } -} - -void AmsWebServer::mqttCert() { - printD(F("Serving /mqtt-cert.html over http...")); - - if(!checkSecurity(1)) - return; - - if(LittleFS.begin()) { - if(LittleFS.exists(FILE_MQTT_CERT)) { - deleteHtml("Certificate", "/mqtt-cert/delete", "mqtt"); - } else { - uploadHtml("Certificate", "/mqtt-cert", "mqtt"); - } - LittleFS.end(); - } else { - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - } -} - -void AmsWebServer::mqttCertUpload() { - if(!checkSecurity(1)) - return; - - uploadFile(FILE_MQTT_CERT); - HTTPUpload& upload = server.upload(); - if(upload.status == UPLOAD_FILE_END) { - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - MqttConfig mqttConfig; - if(config->getMqttConfig(mqttConfig) && mqttConfig.ssl) { - config->setMqttChanged(); - } - } -} - -void AmsWebServer::mqttCertDelete() { - if(!checkSecurity(1)) - return; - - if(!uploading) { // Not an upload - deleteFile(FILE_MQTT_CERT); - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - MqttConfig mqttConfig; - if(config->getMqttConfig(mqttConfig) && mqttConfig.ssl) { - config->setMqttChanged(); - } - } else { - uploading = false; - server.send(200); - } -} - -void AmsWebServer::mqttKey() { - printD(F("Serving /mqtt-key.html over http...")); - - if(!checkSecurity(1)) - return; - - if(LittleFS.begin()) { - if(LittleFS.exists(FILE_MQTT_KEY)) { - deleteHtml("Private key", "/mqtt-key/delete", "mqtt"); - } else { - uploadHtml("Private key", "/mqtt-key", "mqtt"); - } - LittleFS.end(); - } else { - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - } -} - -void AmsWebServer::mqttKeyUpload() { - if(!checkSecurity(1)) - return; - - uploadFile(FILE_MQTT_KEY); - HTTPUpload& upload = server.upload(); - if(upload.status == UPLOAD_FILE_END) { - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - MqttConfig mqttConfig; - if(config->getMqttConfig(mqttConfig) && mqttConfig.ssl) { - config->setMqttChanged(); - } - } -} - -void AmsWebServer::mqttKeyDelete() { - if(!checkSecurity(1)) - return; - - if(!uploading) { // Not an upload - deleteFile(FILE_MQTT_KEY); - server.sendHeader(HEADER_LOCATION,F("/mqtt")); - server.send(303); - MqttConfig mqttConfig; - if(config->getMqttConfig(mqttConfig) && mqttConfig.ssl) { - config->setMqttChanged(); - } - } else { - uploading = false; - server.send(200); - } -} - -void AmsWebServer::factoryResetHtml() { - if(!checkSecurity(1)) - return; - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); - - server.setContentLength(RESET_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent_P(RESET_HTML); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::factoryResetPost() { - if(!checkSecurity(1)) - return; - - printD(F("Performing factory reset")); - if(server.hasArg(F("perform")) && server.arg(F("perform")) == F("true")) { - printD(F("Formatting LittleFS")); - LittleFS.format(); - printD(F("Clearing configuration")); - config->clear(); - printD(F("Setting restart flag and redirecting")); - performRestart = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); - } else { - server.sendHeader(HEADER_LOCATION,F("/")); - server.send(303); - } -} - - -void AmsWebServer::notFound() { - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_1HR); - - server.setContentLength(NOTFOUND_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(404, MIME_HTML, HEAD_HTML); - server.sendContent_P(NOTFOUND_HTML); - server.sendContent_P(FOOT_HTML); -} - - -void AmsWebServer::printD(String fmt, ...) { - va_list args; - va_start(args, fmt); - if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf(String("(AmsWebServer)" + fmt + "\n").c_str(), args); - va_end(args); -} - -void AmsWebServer::printI(String fmt, ...) { - va_list args; - va_start(args, fmt); - if(debugger->isActive(RemoteDebug::INFO)) debugger->printf(String("(AmsWebServer)" + fmt + "\n").c_str(), args); - va_end(args); -} - -void AmsWebServer::printW(String fmt, ...) { - va_list args; - va_start(args, fmt); - if(debugger->isActive(RemoteDebug::WARNING)) debugger->printf(String("(AmsWebServer)" + fmt + "\n").c_str(), args); - va_end(args); -} - -void AmsWebServer::printE(String fmt, ...) { - va_list args; - va_start(args, fmt); - if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf(String("(AmsWebServer)" + fmt + "\n").c_str(), args); - va_end(args); -} - -void AmsWebServer::configFileHtml() { - printD(F("Serving /configfile.html over http...")); - - if(!checkSecurity(1)) - return; - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - - server.setContentLength(CONFIGFILE_HTML_LEN + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent_P(CONFIGFILE_HTML); - server.sendContent_P(FOOT_HTML); -} - -void AmsWebServer::configFileDownload() { - printD(F("Serving /configfile.cfg over http...")); - - if(!checkSecurity(1)) - return; - - bool includeSecrets = server.hasArg(F("ic")) && server.arg(F("ic")) == F("true"); - bool includeWifi = server.hasArg(F("iw")) && server.arg(F("iw")) == F("true"); - bool includeMqtt = server.hasArg(F("im")) && server.arg(F("im")) == F("true"); - bool includeWeb = server.hasArg(F("ie")) && server.arg(F("ie")) == F("true"); - bool includeMeter = server.hasArg(F("it")) && server.arg(F("it")) == F("true"); - bool includeGpio = server.hasArg(F("ig")) && server.arg(F("ig")) == F("true"); - bool includeDomo = server.hasArg(F("id")) && server.arg(F("id")) == F("true"); - bool includeNtp = server.hasArg(F("in")) && server.arg(F("in")) == F("true"); - bool includeEntsoe = server.hasArg(F("is")) && server.arg(F("is")) == F("true"); - bool includeThresholds = server.hasArg(F("ih")) && server.arg(F("ih")) == F("true"); - - SystemConfig sys; - config->getSystemConfig(sys); - - server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE); - server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE); - server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF); - server.sendHeader(F("Content-Disposition"), F("attachment; filename=configfile.cfg")); - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - - server.send_P(200, MIME_PLAIN, PSTR("amsconfig\n")); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("version %s\n"), VERSION)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("boardType %d\n"), sys.boardType)); - - if(includeWifi) { - WiFiConfig wifi; - config->getWiFiConfig(wifi); - if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("hostname %s\n"), wifi.hostname)); - if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ssid %s\n"), wifi.ssid)); - if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("psk %s\n"), wifi.psk)); - if(strlen(wifi.ip) > 0) { - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ip %s\n"), wifi.ip)); - if(strlen(wifi.gateway) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gateway %s\n"), wifi.gateway)); - if(strlen(wifi.subnet) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("subnet %s\n"), wifi.subnet)); - if(strlen(wifi.dns1) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dns1 %s\n"), wifi.dns1)); - if(strlen(wifi.dns2) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dns2 %s\n"), wifi.dns2)); - } - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mdns %d\n"), wifi.mdns ? 1 : 0)); - } - - if(includeMqtt) { - MqttConfig mqtt; - config->getMqttConfig(mqtt); - if(strlen(mqtt.host) > 0) { - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttHost %s\n"), mqtt.host)); - if(mqtt.port > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPort %d\n"), mqtt.port)); - if(strlen(mqtt.clientId) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttClientId %s\n"), mqtt.clientId)); - if(strlen(mqtt.publishTopic) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPublishTopic %s\n"), mqtt.publishTopic)); - if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttUsername %s\n"), mqtt.username)); - if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPassword %s\n"), mqtt.password)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPayloadFormat %d\n"), mqtt.payloadFormat)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttSsl %d\n"), mqtt.ssl ? 1 : 0)); - } - } - - if(includeWeb && includeSecrets) { - WebConfig web; - config->getWebConfig(web); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("webSecurity %d\n"), web.security)); - if(web.security > 0) { - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("webUsername %s\n"), web.username)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("webPassword %s\n"), web.password)); - } - } - - if(includeMeter) { - MeterConfig meter; - config->getMeterConfig(meter); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterBaud %d\n"), meter.baud)); - char parity[4] = ""; - switch(meter.parity) { - case 2: - strcpy_P(parity, PSTR("7N1")); - break; - case 3: - strcpy_P(parity, PSTR("8N1")); - break; - case 10: - strcpy_P(parity, PSTR("7E1")); - break; - case 11: - strcpy_P(parity, PSTR("8E1")); - break; - } - if(strlen(parity) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterParity %s\n"), parity)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterInvert %d\n"), meter.invert ? 1 : 0)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterDistributionSystem %d\n"), meter.distributionSystem)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterMainFuse %d\n"), meter.mainFuse)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterProductionCapacity %d\n"), meter.productionCapacity)); - if(includeSecrets) { - if(meter.encryptionKey[0] != 0x00) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterEncryptionKey %s\n"), toHex(meter.encryptionKey, 16).c_str())); - if(meter.authenticationKey[0] != 0x00) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterAuthenticationKey %s\n"), toHex(meter.authenticationKey, 16).c_str())); - } - } - - if(includeGpio) { - GpioConfig gpio; - config->getGpioConfig(gpio); - if(gpio.hanPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioHanPin %d\n"), gpio.hanPin)); - if(gpio.apPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioApPin %d\n"), gpio.apPin)); - if(gpio.ledPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPin %d\n"), gpio.ledPin)); - if(gpio.ledPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedInverted %d\n"), gpio.ledInverted ? 1 : 0)); - if(gpio.ledPinRed != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPinRed %d\n"), gpio.ledPinRed)); - if(gpio.ledPinGreen != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPinGreen %d\n"), gpio.ledPinGreen)); - if(gpio.ledPinBlue != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPinBlue %d\n"), gpio.ledPinBlue)); - if(gpio.ledPinRed != 0xFF || gpio.ledPinGreen != 0xFF || gpio.ledPinBlue != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedRgbInverted %d\n"), gpio.ledRgbInverted ? 1 : 0)); - if(gpio.tempSensorPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioTempSensorPin %d\n"), gpio.tempSensorPin)); - if(gpio.tempAnalogSensorPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioTempAnalogSensorPin %d\n"), gpio.tempAnalogSensorPin)); - if(gpio.vccPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccPin %d\n"), gpio.vccPin)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccOffset %.2f\n"), gpio.vccOffset / 100.0)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccMultiplier %.3f\n"), gpio.vccMultiplier / 1000.0)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccBootLimit %.1f\n"), gpio.vccBootLimit / 10.0)); - if(gpio.vccPin != 0xFF && gpio.vccResistorGnd != 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccResistorGnd %d\n"), gpio.vccResistorGnd)); - if(gpio.vccPin != 0xFF && gpio.vccResistorVcc != 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccResistorVcc %d\n"), gpio.vccResistorVcc)); - } - - if(includeDomo) { - DomoticzConfig domo; - config->getDomoticzConfig(domo); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzElidx %d\n"), domo.elidx)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzVl1idx %d\n"), domo.vl1idx)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzVl2idx %d\n"), domo.vl2idx)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzVl3idx %d\n"), domo.vl3idx)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzCl1idx %d\n"), domo.cl1idx)); - } - - if(includeNtp) { - NtpConfig ntp; - config->getNtpConfig(ntp); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpEnable %d\n"), ntp.enable ? 1 : 0)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpDhcp %d\n"), ntp.dhcp ? 1 : 0)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpOffset %d\n"), ntp.offset * 10)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpSummerOffset %d\n"), ntp.summerOffset * 10)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpServer %s\n"), ntp.server)); - } - - if(includeEntsoe) { - EntsoeConfig entsoe; - config->getEntsoeConfig(entsoe); - if(strlen(entsoe.token) == 36 && includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("entsoeToken %s\n"), entsoe.token)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("entsoeArea %s\n"), entsoe.area)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("entsoeCurrency %s\n"), entsoe.currency)); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("entsoeMultiplier %.3f\n"), entsoe.multiplier / 1000.0)); - } - - if(includeThresholds) { - EnergyAccountingConfig eac; - config->getEnergyAccountingConfig(eac); - - if(eac.thresholds[9] > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("thresholds %d %d %d %d %d %d %d %d %d %d %d\n"), - eac.thresholds[0], - eac.thresholds[1], - eac.thresholds[2], - eac.thresholds[3], - eac.thresholds[4], - eac.thresholds[5], - eac.thresholds[6], - eac.thresholds[7], - eac.thresholds[8], - eac.thresholds[9], - eac.hours - )); - } - - - if(ds != NULL) { - DayDataPoints day = ds->getDayData(); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dayplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), - day.version, - (int32_t) day.lastMeterReadTime, - day.activeImport, - ds->getHourImport(0), - ds->getHourImport(1), - ds->getHourImport(2), - ds->getHourImport(3), - ds->getHourImport(4), - ds->getHourImport(5), - ds->getHourImport(6), - ds->getHourImport(7), - ds->getHourImport(8), - ds->getHourImport(9), - ds->getHourImport(10), - ds->getHourImport(11), - ds->getHourImport(12), - ds->getHourImport(13), - ds->getHourImport(14), - ds->getHourImport(15), - ds->getHourImport(16), - ds->getHourImport(17), - ds->getHourImport(18), - ds->getHourImport(19), - ds->getHourImport(20), - ds->getHourImport(21), - ds->getHourImport(22), - ds->getHourImport(23) - )); - if(day.activeExport > 0) { - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR(" %u %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"), - day.activeExport, - ds->getHourExport(0), - ds->getHourExport(1), - ds->getHourExport(2), - ds->getHourExport(3), - ds->getHourExport(4), - ds->getHourExport(5), - ds->getHourExport(6), - ds->getHourExport(7), - ds->getHourExport(8), - ds->getHourExport(9), - ds->getHourExport(10), - ds->getHourExport(11), - ds->getHourExport(12), - ds->getHourExport(13), - ds->getHourExport(14), - ds->getHourExport(15), - ds->getHourExport(16), - ds->getHourExport(17), - ds->getHourExport(18), - ds->getHourExport(19), - ds->getHourExport(20), - ds->getHourExport(21), - ds->getHourExport(22), - ds->getHourExport(23) - )); - } else { - server.sendContent(F("\n")); - } - - MonthDataPoints month = ds->getMonthData(); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("monthplot %d %lu %lu %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"), - month.version, - (int32_t) month.lastMeterReadTime, - month.activeImport, - ds->getDayImport(1), - ds->getDayImport(2), - ds->getDayImport(3), - ds->getDayImport(4), - ds->getDayImport(5), - ds->getDayImport(6), - ds->getDayImport(7), - ds->getDayImport(8), - ds->getDayImport(9), - ds->getDayImport(10), - ds->getDayImport(11), - ds->getDayImport(12), - ds->getDayImport(13), - ds->getDayImport(14), - ds->getDayImport(15), - ds->getDayImport(16), - ds->getDayImport(17), - ds->getDayImport(18), - ds->getDayImport(19), - ds->getDayImport(20), - ds->getDayImport(21), - ds->getDayImport(22), - ds->getDayImport(23), - ds->getDayImport(24), - ds->getDayImport(25), - ds->getDayImport(26), - ds->getDayImport(27), - ds->getDayImport(28), - ds->getDayImport(29), - ds->getDayImport(30), - ds->getDayImport(31) - )); - if(month.activeExport > 0) { - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR(" %u %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"), - month.activeExport, - ds->getDayExport(1), - ds->getDayExport(2), - ds->getDayExport(3), - ds->getDayExport(4), - ds->getDayExport(5), - ds->getDayExport(6), - ds->getDayExport(7), - ds->getDayExport(8), - ds->getDayExport(9), - ds->getDayExport(10), - ds->getDayExport(11), - ds->getDayExport(12), - ds->getDayExport(13), - ds->getDayExport(14), - ds->getDayExport(15), - ds->getDayExport(16), - ds->getDayExport(17), - ds->getDayExport(18), - ds->getDayExport(19), - ds->getDayExport(20), - ds->getDayExport(21), - ds->getDayExport(22), - ds->getDayExport(23), - ds->getDayExport(24), - ds->getDayExport(25), - ds->getDayExport(26), - ds->getDayExport(27), - ds->getDayExport(28), - ds->getDayExport(29), - ds->getDayExport(30), - ds->getDayExport(31) - )); - } else { - server.sendContent(F("\n")); - } - } - - if(ea != NULL) { - EnergyAccountingConfig eac; - config->getEnergyAccountingConfig(eac); - EnergyAccountingData ead = ea->getData(); - server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("energyaccounting %d %d %.2f %.2f %.2f %.2f %d %.2f %d %.2f %d %.2f %d %.2f %d %.2f"), - ead.version, - ead.month, - 0.0, - ead.costYesterday / 10.0, - ead.costThisMonth / 1.0, - ead.costLastMonth / 1.0, - ead.peaks[0].day, - ead.peaks[0].value / 100.0, - ead.peaks[1].day, - ead.peaks[1].value / 100.0, - ead.peaks[2].day, - ead.peaks[2].value / 100.0, - ead.peaks[3].day, - ead.peaks[3].value / 100.0, - ead.peaks[4].day, - ead.peaks[4].value / 100.0 - )); - server.sendContent("\n"); - } -} - -void AmsWebServer::configFileUpload() { - if(!checkSecurity(1)) - return; - - HTTPUpload& upload = uploadFile(FILE_CFG); - if(upload.status == UPLOAD_FILE_END) { - performRestart = true; - server.sendHeader(HEADER_LOCATION,F("/restart-wait")); - server.send(303); - } -}