<!doctype html> <html> <head> <title>Index</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> <h1>AHOY</h1> <div id="content" class="content"> <SCRIPT> function promptFunction() { var Text = prompt("This project was started from https://www.mikrocontroller.net/topic/525778 this discussion.\n\n" + "The Hoymiles protocol was decrypted through the voluntary efforts of many participants. ahoy, among others, was developed based on this work. The project is licensed under an Open Source " + "License (https://github.com/lumapu/ahoy/blob/main/LICENSE) GNU General Public License v3.0.\n\n" + "The software was developed to the best of our knowledge and belief. Nevertheless, no liability can be accepted for a malfunction or guarantee loss of the inverter.\n\n" + "Ahoy is freely available. If you paid money for the software, you probably got ripped off.\n\nPlease type in 'YeS', you are accept our Disclaim.", ""); if (Text != "YeS") promptFunction(); else return true; } </SCRIPT> <p> <a href="/live">Visualization</a><br/> <br/> <a href="/setup">Setup</a><br/> <a href="/serial">Webserial & Commands</a><br/> </p> <p><span class="des">Uptime: </span><span id="uptime"></span></p> <p><span class="des">ESP-Time: </span><span id="date"></span></p> <p><span class="des">WiFi RSSI: </span><span id="wifi_rssi"></span> dBm</p> <p> <span class="des">Statistics: </span> <pre id="stat"></pre> <pre id="iv"></pre> <pre id="warn_info"></pre> </p> <p>Every <span id="refresh"></span> seconds the values are updated</p> <div id="note"> This project was started from <a href="https://www.mikrocontroller.net/topic/525778" target="_blank">this discussion. (Mikrocontroller.net)</a><br/> New updates can be found on Github: <a href="https://github.com/lumapu/ahoy" target="_blank">https://github.com/lumapu/ahoy</a><br/> <br/> Please report issues using the feature provided by <a href="https://github.com/lumapu/ahoy/issues">Github</a><br/> <br/> Discuss with us on <a href="https://discord.gg/WzhxEY62mB">Discord</a> <br/> <p class="lic"><a href="https://creativecommons.org/licenses/by-nc-sa/3.0/de">Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/</a><br/> Check the licenses which are published on <a href="https://github.com/lumapu/ahoy">https://github.com/lumapu/ahoy</a> as well</p> </div> </div> <div id="footer"> <p class="left">© 2022</p> <p class="left"><a href="/update">Update Firmware</a></p> <p class="right" id="version"></p> <p class="right"><a href="/reboot">Reboot</a></p> <p class="right"><a href="/api">REST API</a></p> </div> <script type="text/javascript"> var mIntervalSet = false; function apiCb(obj) { var e = document.getElementById("apiResult"); if(obj["success"]) { e.innerHTML = " command excuted"; getAjax("/api/index", parse); } else e.innerHTML = " Error: " + obj["error"]; } function setTime() { var date = new Date(); var offset = date.getTimezoneOffset() * -60; var obj = new Object(); obj.cmd = "set_time"; obj.ts = parseInt(offset + (date.getTime() / 1000)); getAjax("/api/setup", apiCb, "POST", JSON.stringify(obj)); } function parseSys(obj) { // Disclaimer if(obj["disclaimer"] == false) sessionStorage.setItem("gDisclaimer", promptFunction()); document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; document.getElementById("wifi_rssi").innerHTML = obj["wifi_rssi"]; var date = new Date(obj["ts_now"] * 1000); 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); var dSpan = document.getElementById("date") if(0 != obj["ts_now"]) dSpan.innerHTML = date.toLocaleString('de-DE', {timeZone: 'UTC'}); else { var e = inp("set", "sync from browser", 0, ["btn"], "set", "button"); dSpan.appendChild(span("NTP timeserver unreachable. ")); dSpan.appendChild(e); dSpan.appendChild(span("", ["span"], "apiResult")); e.addEventListener("click", setTime); } } function parseStat(obj) { document.getElementById("stat").innerHTML = "RX success: " + obj["rx_success"] + "\nRX fail: " + obj["rx_fail"] + "\nRX no answer: " + obj["rx_fail_answer"] + "\nFrames received: " + obj["frame_cnt"] + "\nTX Cnt: " + obj["tx_cnt"]; } function parseIv(obj) { var html = ""; for(var i of obj) { html += "Inverter #" + i["id"] + ": " + i["name"] + " (v" + i["version"] + ") is "; if(false == i["is_avail"]) html += "not "; html += "available and is "; if(false == i["is_producing"]) html += "not "; html += "producing\n"; if(false == i["is_avail"]) { if(i["ts_last_success"] > 0) { var date = new Date(i["ts_last_success"] * 1000); html += "-> last successful transmission: " + date.toLocaleString('de-DE', {timeZone: 'UTC'}); } } } document.getElementById("iv").innerHTML = html; } function parseWarnInfo(warn, info) { var html = ""; for(var w of warn) { html += "WARN: " + w + "\n"; } for(var i of info) { html += "INFO: " + i + "\n"; } document.getElementById("warn_info").innerHTML = html; } function parse(obj) { if(null != obj) { parseSys(obj["system"]); parseStat(obj["statistics"]); parseIv(obj["inverter"]); parseWarnInfo(obj["warnings"], obj["infos"]); document.getElementById("refresh").innerHTML = obj["refresh_interval"]; if(false == mIntervalSet) { window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000); mIntervalSet = true; } } else document.getElementById("refresh").innerHTML = "n/a"; } getAjax("/api/index", parse); </script> </body> </html>