<!doctype html> <html> <head> <title>Serial Console</title> <link rel="stylesheet" type="text/css" href="style.css"/> <meta name="viewport" content="width=device-width, initial-scale=1"> <script type="text/javascript" src="api.js"></script> </head> <body> <div class="topnav"> <a href="/" class="active">AhoyDTU</a> <a href="javascript:void(0);" class="icon" onclick="topnav()"> <span></span> <span></span> <span></span> </a> <div id="topnav" class="hide"></div> </div> <div id="content" class="content"> <h2>Serial Console</h2> <div class="serial"> <textarea id="serial" cols="80" rows="20" readonly></textarea><br/> connected: <span class="dot" id="connected"></span> Uptime: <span id="uptime"></span> <input type="button" value="clear" class="btn" id="clear"/> <input type="button" value="autoscroll" class="btn" id="scroll"/> <br/> <br/> <br/> <br/> <hr> <h3>Commands</h3> <br/> <label for="iv">Select Inverter:</label> <select name="iv" id="InvID"> </select> <br/> <div id="power"> <input type="button" value="Restart" class="btn" id="restart"/> <input type="button" value="Turn Off" class="btn" id="power_off"/> <input type="button" value="Turn On" class="btn" id="power_on"/> </div> <br/> <br/> <br/> <br/> <br/> <label>Send Power Limit: </label> <input type="number" class="text" name="pwrlimval" maxlength="4"/> <label> </label> <select name="pwrlimcntrl" id="pwrlimcntrl"> <option value="" selected disabled hidden>select the unit and persistence</option> <option value="0">absolute in Watt non persistent</option> <option value="1">relative in percent non persistent</option> <option value="256">absolute in Watt persistent</option> <option value="257">relative in percent persistent</option> </select> <br/> <input type="button" value="Send Power Limit" class="btn" id="sendpwrlim"/> <br/> <p>Ctrl result: <span id="result">n/a</span></p> </div> </div> <div id="footer"> <p class="left">© 2022</p> <p class="right" id="version"></p> </div> <script type="text/javascript"> var mAutoScroll = true; var con = document.getElementById("serial"); var exeOnce = true; function topnav() { toggle("topnav"); } function parseMenu(obj) { var e = document.getElementById("topnav"); e.innerHTML = ""; for(var i = 0; i < obj["name"].length; i ++) { e.appendChild(link(obj["link"][i], obj["name"][i])); } } function parseSys(obj) { var up = obj["ts_uptime"]; var days = parseInt(up / 86400) % 365; var hrs = parseInt(up / 3600) % 24; var min = parseInt(up / 60) % 60; var sec = up % 60; document.getElementById("uptime").innerHTML = days + " Days, " + ("0"+hrs).substr(-2) + ":" + ("0"+min).substr(-2) + ":" + ("0"+sec).substr(-2); if(true == exeOnce) { document.getElementById("version").appendChild( link("https://github.com/lumapu/ahoy/commits/" + obj["build"], "Git SHA: " + obj["build"] + " :: " + obj["version"], "_blank") ); window.setInterval("getAjax('/api/system', parseSys)", 10000); exeOnce = false; } } function parse(root) { parseMenu(root["menu"]); select = document.getElementById('InvID'); if(null == root) return; root = root.inverter; for(var i = 0; i < root.inverter.length; i++) { inv = root.inverter[i]; var opt = document.createElement('option'); opt.value = inv.id; opt.innerHTML = inv.name; select.appendChild(opt); } // set time offset for serial console var obj = new Object(); obj.cmd = "serial_utc_offset"; obj.ts = new Date().getTimezoneOffset() * -60; getAjax("/api/setup", null, "POST", JSON.stringify(obj)); } document.getElementById("clear").addEventListener("click", function() { con.value = ""; }); document.getElementById("scroll").addEventListener("click", function() { mAutoScroll = !mAutoScroll; this.value = (mAutoScroll) ? "autoscroll" : "manual scoll"; }); if (!!window.EventSource) { var source = new EventSource('/events'); source.addEventListener('open', function(e) { document.getElementById("connected").style.backgroundColor = "#0c0"; }, false); source.addEventListener('error', function(e) { if (e.target.readyState != EventSource.OPEN) { document.getElementById("connected").style.backgroundColor = "#f00"; } }, false); source.addEventListener('serial', function(e) { con.value += e.data.replace(/\<rn\>/g, '\r\n'); if(mAutoScroll) con.scrollTop = con.scrollHeight; }, false); } getAjax("/api/system", parseSys); // only for test function ctrlCb(obj) { var e = document.getElementById("result"); if(obj["success"]) e.innerHTML = "ok"; else e.innerHTML = "Error: " + obj["error"]; } function get_selected_iv() { var e = document.getElementById("InvID"); return parseInt(e.value); } const wrapper = document.getElementById('power'); wrapper.addEventListener('click', (event) => { var power = event.target.value; var obj = new Object(); switch (power) { case "Turn On": obj.cmd = 0; break; case "Turn Off": obj.cmd = 1; break; default: obj.cmd = 2; } obj.inverter = get_selected_iv(); obj.tx_request = 81; getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj)); }); document.getElementById("sendpwrlim").addEventListener("click", function() { var val = parseInt(document.getElementsByName('pwrlimval')[0].value); var ctrl = parseInt(document.getElementsByName('pwrlimcntrl')[0].value); if((ctrl == 1 || ctrl == 257) && unit < 2) unit = 2; if(isNaN(val) || isNaN(ctrl)) { var tmp = (isNaN(val)) ? "Value" : "Unit"; document.getElementById("result").textContent = tmp + " is missing"; return; } var obj = new Object(); obj.inverter = get_selected_iv(); obj.cmd = 11; obj.tx_request = 81; obj.payload = [val, ctrl]; getAjax("/api/ctrl", ctrlCb, "POST", JSON.stringify(obj)); }); getAjax("/api/setup", parse); </script> </body> </html>