<!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 / >
< 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 >
< div id = "sun" >
< span class = "des" > Sunrise: < / span > < span id = "sunrise" > < / span > < br >
< span class = "des" > Sunset: < / span > < span id = "sunset" > < / span >
< / div >
< 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" > & copy 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;
var sunrise = new Date(obj["ts_sunrise"] * 1000);
var sunset = new Date(obj["ts_sunset"] * 1000);
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);
}
document.getElementById("sunrise").innerHTML = sunrise.toLocaleString('de-DE', {timeZone: 'UTC'});
document.getElementById("sunset").innerHTML = sunset.toLocaleString('de-DE', {timeZone: 'UTC'});
if(!obj["ts_sun_upd"]) {
var elem = document.getElementById("sun");
elem.parentNode.removeChild(elem);
}
}
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 >