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.
		
		
		
		
		
			
		
			
				
					
					
						
							341 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							341 lines
						
					
					
						
							14 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"> | |
|             function toggle(name, hide) { | |
|                 var elm = document.getElementsByName(name)[0]; | |
|                 if(hide) { | |
|                     if(!elm.classList.contains("hide")) | |
|                         elm.classList.add("hide"); | |
|                 } | |
|                 else | |
|                     elm.classList.remove('hide'); | |
|             } | |
| 
 | |
|             function load() { | |
|                 document.querySelectorAll('input[name^="inv"][name$="Addr"]').forEach(elm => { | |
|                     elm.addEventListener("keyup", (e) => { | |
|                         serial = elm.value.substring(0,4); | |
|                         iv = elm.name.substring(3,4); | |
|                         max = 0; | |
|                         for(i=0;i<4;i++) { | |
|                             toggle("inv"+iv+"ModPwr"+i, true); | |
|                             toggle("inv"+iv+"ModName"+i, true); | |
|                         } | |
|                         toggle("lbl"+iv+"ModPwr", true); | |
|                         toggle("lbl"+iv+"ModName", true); | |
| 
 | |
|                         if(serial == "1161") max = 4; | |
|                         else if(serial == "1141") max = 2; | |
|                         else if(serial == "1121") max = 1; | |
| 
 | |
|                         for(i=0;i<max;i++) { | |
|                             toggle("inv"+iv+"ModPwr"+i, false); | |
|                             toggle("inv"+iv+"ModName"+i, false); | |
|                         } | |
|                         if(max != 0) { | |
|                             toggle("lbl"+iv+"ModPwr", false); | |
|                             toggle("lbl"+iv+"ModName", false); | |
|                         } | |
|                     }); | |
|                     evt = document.createEvent("HTMLEvents"); | |
|                     evt.initEvent("keyup", false, true); | |
|                     elm.dispatchEvent(evt); | |
|                 }); | |
|             } | |
|         </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"/> | |
|                     </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" name="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"/> | |
|                     </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"/> | |
|                         <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="text" class="text" name="mqttPwd"/> | |
|                         <label for="mqttTopic">Topic</label> | |
|                         <input type="text" class="text" name="mqttTopic"/> | |
|                     </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"/> | |
|                 </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"> | |
|             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"; | |
|                 }); | |
|             } | |
| 
 | |
|             var highestId = 0; | |
|             var maxInv = 0; | |
| 
 | |
|             document.getElementsByName("btnAdd")[0].addEventListener("click", function() { | |
|                 if(highestId < (maxInv-1)) | |
|                     ivHtml(JSON.parse('{"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""],"power_limit":1500,"power_limit_option":65535}'), highestId + 1); | |
|             }); | |
| 
 | |
|             function getAjax(url, ptr) { | |
|                 var http = new XMLHttpRequest(); | |
|                 if(http != null) { | |
|                    http.open("GET", url, true); | |
|                    http.onreadystatechange = p; | |
|                    http.send(null); | |
|                 } | |
|                 function p() { | |
|                     if(http.readyState == 4) | |
|                         ptr(JSON.parse(http.responseText)); | |
|                 } | |
|             } | |
| 
 | |
|             function des(val) { | |
|                 e = document.createElement('p'); | |
|                 e.classList.add("subdes"); | |
|                 e.innerHTML = val; | |
|                 return e; | |
|             } | |
| 
 | |
|             function lbl(id, val) { | |
|                 e = document.createElement('label'); | |
|                 e.htmlFor = id; | |
|                 e.innerHTML = val; | |
|                 return e; | |
|             } | |
| 
 | |
|             function inp(name, val, max=32, cl=["text"]) { | |
|                 e = document.createElement('input'); | |
|                 e.classList.add(...cl); | |
|                 e.name = name; | |
|                 e.value = val; | |
|                 e.maxLength = max; | |
|                 return e; | |
|             } | |
| 
 | |
|             function sel(name, opt, selId) { | |
|                 e = document.createElement('select'); | |
|                 e.name = name; | |
|                 for(it of opt) { | |
|                     o = document.createElement('option'); | |
|                     o.value = it[0]; | |
|                     o.innerHTML = it[1]; | |
|                     if(it[0] == selId) | |
|                         o.selected = true; | |
|                     e.appendChild(o); | |
|                 } | |
|                 return e; | |
|             } | |
| 
 | |
|             function div(cl) { | |
|                 e = document.createElement('div'); | |
|                 e.classList.add(cl); | |
|                 return e; | |
|             } | |
| 
 | |
|             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; | |
| 
 | |
|                 for(var i of [["Addr", "serial", "Address*", 12], ["Name", "name", "Name*", 32], ["ActivePowerLimit", "power_limit", "Active Power Limit", 5]]) { | |
|                     iv.appendChild(lbl(id + i[0], i[2])); | |
|                     iv.appendChild(inp(id + i[0], obj[i[1]], i[3])); | |
|                 } | |
| 
 | |
|                 iv.appendChild(lbl(id + "ActivePowerLimitConType", "Active Power Limit Control Type")); | |
|                 iv.appendChild(sel(id + "ActivePowerLimitConType", [ | |
|                     [65535, "no power limit"], | |
|                     [0, "absolute in Watt non persistent"], | |
|                     [1, "absolute in Watt persistent"], | |
|                     [256, "relativ in percent non persistent"], | |
|                     [257, "relativ in percent persistent"] | |
|                 ], obj.power_limit_option)); | |
| 
 | |
|                 for(var j of [["ModPwr", "ch_max_power", "Max Module Power (Wp)"], ["ModName", "ch_name", "Module Name"]]) { | |
|                     iv.appendChild(lbl(id + j[0], j[2])); | |
|                     d = div(j[0]); | |
|                     i = 0; | |
|                     for(it of obj[j[1]]) { | |
|                         d.appendChild(inp(id + j[0] + i, it, 4, ["text", "sh"])); | |
|                         i++; | |
|                     } | |
|                     iv.appendChild(d); | |
|                 } | |
|             } | |
| 
 | |
|             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 parsePinout(obj) { | |
|                 var e = document.getElementById("pinout"); | |
|                 pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; | |
|                 for(p of pins) { | |
|                     e.appendChild(lbl(p[1], p[0].toUpperCase())); | |
|                     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]])); | |
|                 } | |
|             } | |
| 
 | |
|             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"]; | |
|             } | |
| 
 | |
|             getAjax("/api/system", parseSys); | |
|             getAjax("/api/inverter/list", parseIv); | |
|             getAjax("/api/mqtt", parseMqtt); | |
|             getAjax("/api/ntp", parseNtp); | |
|             getAjax("/api/pinout", parsePinout); | |
|             getAjax("/api/radio", parseRadio); | |
|             getAjax("/api/serial", parseSerial); | |
|         </script> | |
|     </body> | |
| </html>
 | |
| 
 |