mirror of https://github.com/lumapu/ahoy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
388 lines
17 KiB
388 lines
17 KiB
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>Setup</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>
|
|
<script type="text/javascript">
|
|
function load() {
|
|
for(it of document.getElementsByClassName("s_collapsible")) {
|
|
it.addEventListener("click", function() {
|
|
this.classList.toggle("active");
|
|
var content = this.nextElementSibling;
|
|
content.style.display = (content.style.display === "block") ? "none" : "block";
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body onload="load()">
|
|
<h1>Setup</h1>
|
|
<div id="setup" class="content">
|
|
<div id="content">
|
|
<a class="erase" href="/erase">ERASE SETTINGS (not WiFi)</a>
|
|
|
|
<form method="post" action="/save">
|
|
<fieldset>
|
|
<legend class="des">Device Host Name</legend>
|
|
<label for="device">Device Name</label>
|
|
<input type="text" name="device" class="text"/>
|
|
<input type="hidden" name="disclaimer" value="false" id="disclaimer">
|
|
</fieldset>
|
|
|
|
<button type="button" class="s_collapsible">WiFi</button>
|
|
<div class="s_content">
|
|
<fieldset>
|
|
<legend class="des">WiFi</legend>
|
|
<p>Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.</p>
|
|
<label for="ssid">SSID</label>
|
|
<input type="text" name="ssid" class="text"/>
|
|
<label for="pwd">Password</label>
|
|
<input type="password" class="text" name="pwd" value="{PWD}"/>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<button type="button" class="s_collapsible">Inverter</button>
|
|
<div class="s_content">
|
|
<fieldset>
|
|
<legend class="des">Inverter</legend>
|
|
<div id="inverter"></div><br/>
|
|
<input type="button" id="btnAdd" value="Add Inverter"/>
|
|
<p class="subdes">General</p>
|
|
<label for="invInterval">Interval [s]</label>
|
|
<input type="text" class="text" name="invInterval"/>
|
|
<label for="invRetry">Max retries per Payload</label>
|
|
<input type="text" class="text" name="invRetry"/>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<button type="button" class="s_collapsible">NTP Server</button>
|
|
<div class="s_content">
|
|
<fieldset>
|
|
<legend class="des">NTP Server</legend>
|
|
<label for="ntpAddr">NTP Server / IP</label>
|
|
<input type="text" class="text" name="ntpAddr"/>
|
|
<label for="ntpPort">NTP Port</label>
|
|
<input type="text" class="text" name="ntpPort"/>
|
|
<label for="ntpBtn">set system time</label>
|
|
<input type="button" name="ntpBtn" id="ntpBtn" class="btn" value="from browser" onclick="setTime()"/>
|
|
<input type="button" name="ntpSync" id="ntpSync" class="btn" value="sync NTP" onclick="syncTime()"/>
|
|
<span id="apiResultNtp"></span>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<button type="button" class="s_collapsible">Sunrise & Sunset</button>
|
|
<div class="s_content">
|
|
<fieldset>
|
|
<legend class="des">Sunrise & Sunset</legend>
|
|
<label for="sunLat">Latitude (decimal)</label>
|
|
<input type="text" class="text" name="sunLat"/>
|
|
<label for="sunLon">Longitude (decimal)</label>
|
|
<input type="text" class="text" name="sunLon"/>
|
|
<br>
|
|
<label for="sunDisNightCom">disable night communication</label>
|
|
<input type="checkbox" class="cb" name="sunDisNightCom"/><br/>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<button type="button" class="s_collapsible">MQTT</button>
|
|
<div class="s_content">
|
|
<fieldset>
|
|
<legend class="des">MQTT</legend>
|
|
<label for="mqttAddr">Broker / Server IP</label>
|
|
<input type="text" class="text" name="mqttAddr" maxlength="32" />
|
|
<label for="mqttPort">Port</label>
|
|
<input type="text" class="text" name="mqttPort"/>
|
|
<label for="mqttUser">Username (optional)</label>
|
|
<input type="text" class="text" name="mqttUser"/>
|
|
<label for="mqttPwd">Password (optional)</label>
|
|
<input type="password" class="text" name="mqttPwd"/>
|
|
<label for="mqttTopic">Topic</label>
|
|
<input type="text" class="text" name="mqttTopic"/>
|
|
<label for="mqttBtn">Discovery Config (homeassistant)</label>
|
|
<input type="button" name="mqttDiscovery" id="mqttDiscovery" class="btn" value="send" onclick="sendDiscoveryConfig()"/>
|
|
<span id="apiResultMqtt"></span>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<button type="button" class="s_collapsible">System Config</button>
|
|
<div class="s_content">
|
|
<fieldset>
|
|
<legend class="des">System Config</legend>
|
|
<p class="des">Pinout (Wemos)</p>
|
|
<div id="pinout"></div>
|
|
|
|
<p class="des">Radio (NRF24L01+)</p>
|
|
<div id="rf24"></div>
|
|
|
|
<p class="des">Serial Console</p>
|
|
<label for="serEn">print inverter data</label>
|
|
<input type="checkbox" class="cb" name="serEn"/><br/>
|
|
<label for="serDbg">Serial Debug</label>
|
|
<input type="checkbox" class="cb" name="serDbg"/><br/>
|
|
<label for="serIntvl">Interval [s]</label>
|
|
<input type="text" class="text" name="serIntvl"/>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<label for="reboot">Reboot device after successful save</label>
|
|
<input type="checkbox" class="cb" name="reboot"/>
|
|
<input type="submit" value="save" class="btn right"/><br/>
|
|
<br/>
|
|
<a href="/get_setup" target="_blank">Download your settings (JSON file)</a> (only saved values)
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div id="footer">
|
|
<p class="left"><a href="/">Home</a></p>
|
|
<p class="left"><a href="/update">Update Firmware</a></p>
|
|
<p class="right" id="version"></p>
|
|
<p class="right"><a href="/factory">Factory Reset</a></p>
|
|
<p class="right"><a href="/reboot">Reboot</a></p>
|
|
</div>
|
|
<script type="text/javascript">
|
|
var highestId = 0;
|
|
var maxInv = 0;
|
|
|
|
const re = /11[2,4,6]1.*/;
|
|
|
|
document.getElementById("btnAdd").addEventListener("click", function() {
|
|
if(highestId <= (maxInv-1))
|
|
ivHtml(JSON.parse('{"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""]}'), highestId + 1);
|
|
});
|
|
|
|
function apiCbNtp(obj) {
|
|
var e = document.getElementById("apiResultNtp");
|
|
if(obj["success"])
|
|
e.innerHTML = "command excuted";
|
|
else
|
|
e.innerHTML = "Error: " + obj["error"];
|
|
}
|
|
|
|
function apiCbMqtt(obj) {
|
|
var e = document.getElementById("apiResultMqtt");
|
|
if(obj["success"])
|
|
e.innerHTML = "command excuted";
|
|
else
|
|
e.innerHTML = "Error: " + obj["error"];
|
|
}
|
|
|
|
function setTime() {
|
|
var date = new Date();
|
|
var obj = new Object();
|
|
obj.cmd = "set_time";
|
|
obj.ts = parseInt(date.getTime() / 1000);
|
|
getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj));
|
|
}
|
|
|
|
function syncTime() {
|
|
var obj = new Object();
|
|
obj.cmd = "sync_ntp";
|
|
getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj));
|
|
}
|
|
|
|
function sendDiscoveryConfig() {
|
|
var obj = new Object();
|
|
obj.cmd = "discovery_cfg";
|
|
getAjax("/api/setup", apiCbMqtt, "POST", JSON.stringify(obj));
|
|
}
|
|
|
|
function delIv() {
|
|
var id = this.id.substring(0,4);
|
|
var e = document.getElementsByName(id + "Addr")[0];
|
|
e.value = "";
|
|
e.dispatchEvent(new Event("keyup"));
|
|
document.getElementsByName(id + "Name")[0].value = "";
|
|
}
|
|
|
|
function ivHtml(obj, id) {
|
|
highestId = id;
|
|
if(highestId == (maxInv - 1))
|
|
toggle("btnAdd", true);
|
|
iv = document.getElementById("inverter");
|
|
iv.appendChild(des("Inverter " + id));
|
|
id = "inv" + id;
|
|
|
|
|
|
iv.appendChild(lbl(id + "Addr", "Address*"));
|
|
var addr = inp(id + "Addr", obj["serial"], 12)
|
|
iv.appendChild(addr);
|
|
addr.addEventListener("keyup", (e) => {
|
|
var serial = addr.value.substring(0,4);
|
|
var max = 0;
|
|
for(var i=0;i<4;i++) {
|
|
toggle(id+"ModPwr"+i, true);
|
|
toggle(id+"ModName"+i, true);
|
|
}
|
|
toggle("lbl"+id+"ModPwr", true);
|
|
toggle("lbl"+id+"ModName", true);
|
|
|
|
if(serial == "1161") max = 4;
|
|
else if(serial == "1141") max = 2;
|
|
else if(serial == "1121") max = 1;
|
|
|
|
for(var i=0;i<max;i++) {
|
|
toggle(id+"ModPwr"+i, false);
|
|
toggle(id+"ModName"+i, false);
|
|
}
|
|
if(max != 0) {
|
|
toggle("lbl"+id+"ModPwr", false);
|
|
toggle("lbl"+id+"ModName", false);
|
|
}
|
|
});
|
|
|
|
for(var i of [["Name", "name", "Name*", 32]]) {
|
|
iv.appendChild(lbl(id + i[0], i[2]));
|
|
iv.appendChild(inp(id + i[0], obj[i[1]], i[3]));
|
|
}
|
|
|
|
for(var j of [["ModPwr", "ch_max_power", "Max Module Power (Wp)", 4], ["ModName", "ch_name", "Module Name", 16]]) {
|
|
var cl = (re.test(obj["serial"])) ? null : ["hide"];
|
|
iv.appendChild(lbl(null, j[2], cl, "lbl" + id + j[0]));
|
|
d = div([j[0]]);
|
|
i = 0;
|
|
cl = (re.test(obj["serial"])) ? ["text", "sh"] : ["text", "sh", "hide"];
|
|
for(it of obj[j[1]]) {
|
|
d.appendChild(inp(id + j[0] + i, it, j[3], cl, id + j[0] + i));
|
|
i++;
|
|
}
|
|
iv.appendChild(d);
|
|
}
|
|
iv.appendChild(br());
|
|
iv.appendChild(lbl(id + "lbldel", "Delete"));
|
|
var del = inp(id+"del", "X", 0, ["btn", "btnDel"], id+"del", "button");
|
|
iv.appendChild(del);
|
|
del.addEventListener("click", delIv);
|
|
}
|
|
|
|
function ivGlob(obj) {
|
|
for(var i of [["invInterval", "interval"], ["invRetry", "retries"]])
|
|
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
|
}
|
|
|
|
function parseSys(obj) {
|
|
for(var i of [["device", "device_name"], ["ssid", "ssid"]])
|
|
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
|
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"];
|
|
}
|
|
|
|
function parseIv(obj) {
|
|
for(var i = 0; i < obj.inverter.length; i++)
|
|
ivHtml(obj.inverter[i], i);
|
|
ivGlob(obj);
|
|
maxInv = obj["max_num_inverters"];
|
|
}
|
|
|
|
function parseMqtt(obj) {
|
|
for(var i of [["Addr", "broker"], ["Port", "port"], ["User", "user"], ["Pwd", "pwd"], ["Topic", "topic"]])
|
|
document.getElementsByName("mqtt"+i[0])[0].value = obj[i[1]];
|
|
}
|
|
|
|
function parseNtp(obj) {
|
|
for(var i of [["ntpAddr", "addr"], ["ntpPort", "port"]])
|
|
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
|
}
|
|
|
|
function parseSun(obj) {
|
|
document.getElementsByName("sunLat")[0].value = obj["lat"];
|
|
document.getElementsByName("sunLon")[0].value = obj["lon"];
|
|
document.getElementsByName("sunDisNightCom")[0].checked = obj["disnightcom"];
|
|
}
|
|
|
|
function parsePinout(obj, type) {
|
|
var e = document.getElementById("pinout");
|
|
pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']];
|
|
for(p of pins) {
|
|
e.appendChild(lbl(p[1], p[0].toUpperCase()));
|
|
if("ESP8266" == type) {
|
|
e.appendChild(sel(p[1], [
|
|
[0, "D3 (GPIO0)"],
|
|
[1, "TX (GPIO1)"],
|
|
[2, "D4 (GPIO2)"],
|
|
[3, "RX (GPIO3)"],
|
|
[4, "D2 (GPIO4)"],
|
|
[5, "D1 (GPIO5)"],
|
|
[6, "GPIO6"],
|
|
[7, "GPIO7"],
|
|
[8, "GPIO8"],
|
|
[9, "GPIO9"],
|
|
[10, "GPIO10"],
|
|
[11, "GPIO11"],
|
|
[12, "D6 (GPIO12)"],
|
|
[13, "D7 (GPIO13)"],
|
|
[14, "D5 (GPIO14)"],
|
|
[15, "D8 (GPIO15)"],
|
|
[16, "D0 (GPIO16 - no IRQ!)"]
|
|
], obj[p[0]]));
|
|
}
|
|
else {
|
|
e.appendChild(sel(p[1], [
|
|
[0, "GPIO0"],
|
|
[1, "TX (GPIO1)"],
|
|
[2, "GPIO2 (LED)"],
|
|
[3, "RX (GPIO3)"],
|
|
[4, "GPIO4"],
|
|
[5, "GPIO5"],
|
|
[12, "GPIO12"],
|
|
[13, "GPIO13"],
|
|
[14, "GPIO14"],
|
|
[15, "GPIO15"],
|
|
[16, "GPIO16"],
|
|
[17, "GPIO17"],
|
|
[18, "GPIO18"],
|
|
[19, "GPIO19"],
|
|
[21, "GPIO21"],
|
|
[22, "GPIO22"],
|
|
[23, "GPIO23"],
|
|
[25, "GPIO25"],
|
|
[26, "GPIO26"],
|
|
[27, "GPIO27"],
|
|
[32, "GPIO32"],
|
|
[33, "GPIO33"],
|
|
[34, "GPIO34"],
|
|
[35, "GPIO35"],
|
|
[36, "VP (GPIO36)"],
|
|
[39, "VN (GPIO39)"]
|
|
], obj[p[0]]));
|
|
}
|
|
}
|
|
}
|
|
|
|
function parseRadio(obj) {
|
|
var e = document.getElementById("rf24");
|
|
e.appendChild(lbl("rf24Power", "Amplifier Power Level"));
|
|
e.appendChild(sel("rf24Power", [
|
|
[0, "MIN"],
|
|
[1, "LOW"],
|
|
[2, "HIGH"],
|
|
[3, "MAX"]
|
|
], obj["power_level"]));
|
|
}
|
|
|
|
function parseSerial(obj) {
|
|
for(var i of [["serEn", "show_live_data"], ["serDbg", "debug"]])
|
|
document.getElementsByName(i[0])[0].checked = obj[i[1]];
|
|
document.getElementsByName("serIntvl")[0].value = obj["interval"];
|
|
}
|
|
|
|
function parse(root) {
|
|
if(null != root) {
|
|
parseSys(root["system"]);
|
|
parseIv(root["inverter"]);
|
|
parseMqtt(root["mqtt"]);
|
|
parseNtp(root["ntp"]);
|
|
parseSun(root["sun"]);
|
|
parsePinout(root["pinout"], root["system"]["esp_type"]);
|
|
parseRadio(root["radio"]);
|
|
parseSerial(root["serial"]);
|
|
}
|
|
}
|
|
|
|
hiddenInput = document.getElementById("disclaimer")
|
|
hiddenInput.value = sessionStorage.getItem("gDisclaimer");
|
|
|
|
getAjax("/api/setup", parse);
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|