kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
web ui usability enhancements
rodzic
981ecc8044
commit
7db0e8ff11
|
@ -214,9 +214,24 @@ void setupChannelList() {
|
|||
file.close();
|
||||
}
|
||||
|
||||
const char *HTMLHEAD="<html><head> <meta charset=\"UTF-8\"> <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">";
|
||||
void HTMLBODY(char *ptr, const char *which) {
|
||||
strcat(ptr, "<body><form class=\"wrapper\" action=\"");
|
||||
strcat(ptr, which);
|
||||
strcat(ptr, "\" method=\"post\"><div class=\"content\">");
|
||||
}
|
||||
void HTMLBODYEND(char *ptr) {
|
||||
strcat(ptr, "</div></form></body></html>");
|
||||
}
|
||||
void HTMLSAVEBUTTON(char *ptr) {
|
||||
strcat(ptr, "</div><div class=\"footer\"><input type=\"submit\" class=\"save\" value=\"Save changes\"/>");
|
||||
}
|
||||
|
||||
const char *createQRGForm() {
|
||||
char *ptr = message;
|
||||
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">");
|
||||
strcpy(ptr, HTMLHEAD);
|
||||
strcat(ptr, "<script src=\"rdz.js\"/> <script> window.onload = prep; </script></head>");
|
||||
/*
|
||||
strcat(ptr, "<script type=\"text/javascript\">"
|
||||
"let stypes=new Map();"
|
||||
"stypes.set('4', 'RS41');"
|
||||
|
@ -241,13 +256,15 @@ const char *createQRGForm() {
|
|||
" } txt.replaceWith(sel); } } "
|
||||
" window.onload = prep; "
|
||||
"</script>");
|
||||
|
||||
strcat(ptr, "</head><body><form action=\"qrg.html\" method=\"post\"><table><tr><th>ID</th><th>Active</th><th>Freq</th><th>Launchsite</th><th>Mode</th></tr>");
|
||||
*/
|
||||
HTMLBODY(ptr, "qrg.html");
|
||||
//strcat(ptr, "<body><form class=\"wrapper\" action=\"qrg.html\" method=\"post\"><div class=\"content\"><table><tr><th>ID</th><th>Active</th><th>Freq</th><th>Launchsite</th><th>Mode</th></tr>");
|
||||
strcat(ptr, "<table><tr><th>ID</th><th>Active</th><th>Freq</th><th>Launchsite</th><th>Mode</th></tr>");
|
||||
for (int i = 0; i < sonde.config.maxsonde; i++) {
|
||||
//String s = sondeTypeSelect(i >= sonde.nSonde ? 2 : sonde.sondeList[i].type);
|
||||
String site = sonde.sondeList[i].launchsite;
|
||||
sprintf(ptr + strlen(ptr), "<tr><td>%d</td><td><input name=\"A%d\" type=\"checkbox\" %s/></td>"
|
||||
"<td><input name=\"F%d\" type=\"text\" value=\"%3.3f\"></td>"
|
||||
"<td><input name=\"F%d\" type=\"text\" width=12 value=\"%3.3f\"></td>"
|
||||
"<td><input name=\"S%d\" type=\"text\" value=\"%s\"></td>"
|
||||
//"<td><select name=\"T%d\">%s</select></td>",
|
||||
"<td><input class='stype' name='T%d' value='%c'>",
|
||||
|
@ -258,7 +275,10 @@ const char *createQRGForm() {
|
|||
i + 1, i >= sonde.nSonde ? 2 : sondeTypeChar[sonde.sondeList[i].type] );
|
||||
//i + 1, s.c_str());
|
||||
}
|
||||
strcat(ptr, "</table><input type=\"submit\" value=\"Update\"/></form></body></html>");
|
||||
strcat(ptr, "</table>");
|
||||
//</div><div class=\"footer\"><input type=\"submit\" class=\"update\" value=\"Update\"/>");
|
||||
HTMLSAVEBUTTON(ptr);
|
||||
HTMLBODYEND(ptr);
|
||||
Serial.printf("QRG form: size=%d bytes\n", strlen(message));
|
||||
return message;
|
||||
}
|
||||
|
@ -353,7 +373,9 @@ void setupWifiList() {
|
|||
const char *createWIFIForm() {
|
||||
char *ptr = message;
|
||||
char tmp[4];
|
||||
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"wifi.html\" method=\"post\"><table><tr><th>Nr</th><th>SSID</th><th>Password</th></tr>");
|
||||
strcpy(ptr, HTMLHEAD); strcat(ptr, "</head>");
|
||||
HTMLBODY(ptr, "wifi.html");
|
||||
strcat(ptr, "<table><tr><th>Nr</th><th>SSID</th><th>Password</th></tr>");
|
||||
for (int i = 0; i < MAX_WIFI; i++) {
|
||||
sprintf(tmp, "%d", i);
|
||||
sprintf(ptr + strlen(ptr), "<tr><td>%s</td><td><input name=\"S%d\" type=\"text\" value=\"%s\"/></td>"
|
||||
|
@ -362,7 +384,10 @@ const char *createWIFIForm() {
|
|||
i + 1, i < nNetworks ? networks[i].id.c_str() : "",
|
||||
i + 1, i < nNetworks ? networks[i].pw.c_str() : "");
|
||||
}
|
||||
strcat(ptr, "</table><input type=\"submit\" value=\"Update\"></input></form></body></html>");
|
||||
strcat(ptr, "</table>");
|
||||
//</div><div class=\"footer\"><input type=\"submit\" class=\"update\" value=\"Update\"/>");
|
||||
HTMLSAVEBUTTON(ptr);
|
||||
HTMLBODYEND(ptr);
|
||||
Serial.printf("WIFI form: size=%d bytes\n", strlen(message));
|
||||
return message;
|
||||
}
|
||||
|
@ -436,7 +461,8 @@ void addSondeStatus(char *ptr, int i)
|
|||
|
||||
const char *createStatusForm() {
|
||||
char *ptr = message;
|
||||
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"><meta http-equiv=\"refresh\" content=\"5\"></head><body>");
|
||||
strcpy(ptr, HTMLHEAD);
|
||||
strcat(ptr, "<meta http-equiv=\"refresh\" content=\"5\"></head><body>");
|
||||
|
||||
for (int i = 0; i < sonde.nSonde; i++) {
|
||||
int snum = (i + sonde.currentSonde) % sonde.nSonde;
|
||||
|
@ -607,7 +633,9 @@ void addConfigInt8List(char *ptr, int idx, const char *label, int8_t *list) {
|
|||
|
||||
const char *createConfigForm() {
|
||||
char *ptr = message;
|
||||
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"config.html\" method=\"post\"><table><tr><th>Option</th><th>Value</th></tr>");
|
||||
strcpy(ptr, HTMLHEAD); strcat(ptr, "</head>");
|
||||
HTMLBODY(ptr, "config.html");
|
||||
strcat(ptr, "<table><tr><th>Option</th><th>Value</th></tr>");
|
||||
for (int i = 0; i < N_CONFIG; i++) {
|
||||
switch (config_list[i].type) {
|
||||
case -5: // Heading
|
||||
|
@ -636,7 +664,10 @@ const char *createConfigForm() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
strcat(ptr, "</table><input type=\"submit\" value=\"Update\"></input></form></body></html>");
|
||||
strcat(ptr, "</table>");
|
||||
//</div><div class=\"footer\"><input type=\"submit\" class=\"update\" value=\"Update\"/>");
|
||||
HTMLSAVEBUTTON(ptr);
|
||||
HTMLBODYEND(ptr);
|
||||
Serial.printf("Config form: size=%d bytes\n", strlen(message));
|
||||
return message;
|
||||
}
|
||||
|
@ -695,21 +726,23 @@ const char *handleConfigPost(AsyncWebServerRequest *request) {
|
|||
|
||||
const char *ctrlid[] = {"rx", "scan", "spec", "wifi", "rx2", "scan2", "spec2", "wifi2"};
|
||||
|
||||
const char *ctrllabel[] = {"Receiver (short keypress)", "Scanner (double keypress)", "Spectrum (medium keypress)", "WiFi (long keypress)",
|
||||
"Button 2 (short keypress)", "Button 2 (double keypress)", "Button 2 (medium keypress)", "Button 2 (long keypress)"
|
||||
const char *ctrllabel[] = {"Receiver/next freq. (short keypress)", "Scanner (double keypress)", "Spectrum (medium keypress)", "WiFi (long keypress)",
|
||||
"Button 2/next screen (short keypress)", "Button 2 (double keypress)", "Button 2 (medium keypress)", "Button 2 (long keypress)"
|
||||
};
|
||||
|
||||
const char *createControlForm() {
|
||||
char *ptr = message;
|
||||
strcpy(ptr, "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"></head><body><form action=\"control.html\" method=\"post\">");
|
||||
strcpy(ptr, HTMLHEAD); strcat(ptr, "</head>");
|
||||
HTMLBODY(ptr, "control.html");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
strcat(ptr, "<input type=\"submit\" name=\"");
|
||||
strcat(ptr, "<input class=\"ctlbtn\" type=\"submit\" name=\"");
|
||||
strcat(ptr, ctrlid[i]);
|
||||
strcat(ptr, "\" value=\"");
|
||||
strcat(ptr, ctrllabel[i]);
|
||||
strcat(ptr, "\"></input><br>");
|
||||
strcat(ptr, "\"></input>");
|
||||
if(i==3) { strcat(ptr, "<p></p>"); }
|
||||
}
|
||||
strcat(ptr, "</form></body></html>");
|
||||
HTMLBODYEND(ptr);
|
||||
Serial.printf("Control form: size=%d bytes\n", strlen(message));
|
||||
return message;
|
||||
}
|
||||
|
|
|
@ -1,64 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>RDZSonde Server</title>
|
||||
<title>rdzTTGOsonde Server</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="data:,">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h2>RDZSonde Server</h2>
|
||||
<!--
|
||||
<p>GPIO state: <strong> %STATE%</strong></p>
|
||||
<p><a href="/on"><button class="button">ON</button></a></p>
|
||||
<p><a href="/off"><button class="button button2">OFF</button></a></p>
|
||||
-->
|
||||
<div class="wrapper"><div class="header">
|
||||
<h1>RDZSonde Server</h1>
|
||||
|
||||
<div class="tab">
|
||||
<button class="tablinks" onclick="selTab(event,'QRG')" id="defaultTab">QRG</button>
|
||||
<button class="tablinks" onclick="selTab(event,'WiFi')">WiFi</button>
|
||||
<button class="tablinks" onclick="selTab(event,'Data')">Data</button>
|
||||
<!-- <button class="tablinks" onclick="selTab(event,'SondeMap')">SondeMap</button> -->
|
||||
<button class="tablinks" onclick="selTab(event,'Config')">Config</button>
|
||||
<button class="tablinks" onclick="selTab(event,'Control')">Control</button>
|
||||
<button class="tablinks" onclick="selTab(event,'About')">About</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="QRG" class="tabcontent" data-src="qrg.html">
|
||||
<h3> QRG - Setup</h3>
|
||||
<iframe src="" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||
<iframe class="tci" src="" ></iframe>
|
||||
</div>
|
||||
|
||||
<div id="WiFi" class="tabcontent" data-src="wifi.html">
|
||||
<h3> WiFi - Settings</h3>
|
||||
<iframe src="" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||
<iframe class="tci" src="" ></iframe>
|
||||
</div>
|
||||
|
||||
<div id="Data" class="tabcontent" data-src="status.html">
|
||||
<h3>Data</h3>
|
||||
<iframe src="" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||
<iframe class="tci" src="" ></iframe>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div id="SondeMap" class="tabcontent" data-src="https://wetterson.de/karte/">
|
||||
<iframe src="" style="border:none;" width="98%%" height="98%%"></iframe>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div id="Config" class="tabcontent" data-src="config.html">
|
||||
<h3>Configuration</h3>
|
||||
<iframe src="" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||
<iframe class="tci" src="" ></iframe>
|
||||
</div>
|
||||
|
||||
<div id="Control" class="tabcontent" data-src="control.html">
|
||||
<h3>Control</h3>
|
||||
<iframe src="" style="border:none;" width="100%%" height="100%%"></iframe>
|
||||
<iframe class="tci" src="" ></iframe>
|
||||
</div>
|
||||
|
||||
<div id="About" class="tabcontent">
|
||||
<h3>About</h3>
|
||||
<div class="tci">
|
||||
%VERSION_NAME%<br>
|
||||
Copyright © 2019-2020 by Hansi Reiser, DL9RDZ<br>
|
||||
Copyright © 2019-2021 by Hansi Reiser, DL9RDZ<br>
|
||||
(version %VERSION_ID%)<br><br>
|
||||
with contributions by Vigor and Xavier (M20 support), <a href="https://www.dl2mf.de/" target="_blank">Meinhard Guenther, DL2MF</a>,
|
||||
<a href="https://github.com/bazjo">Johannes</a>, <a href="http://www.p1337.synology.me/dokuwiki/doku.php?id=public:wettersonden">Robert Stefanowicz</a>,
|
||||
|
@ -68,14 +54,16 @@
|
|||
<br>
|
||||
Autodetect info: %AUTODETECT_INFO%<br>
|
||||
<br>
|
||||
This program is free software; you can redistribute it and/or<br>
|
||||
modify it under the terms of the GNU General Public License as<br>
|
||||
published by the Free Software Foundation; either version 2 of<br>
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.<br>
|
||||
see <a href="https://www.gnu.org/licenses/gpl-2.0.txt">https://www.gnu.org/licenses/gpl-2.0.txt</a>
|
||||
for details
|
||||
See <a href="https://www.gnu.org/licenses/gpl-2.0.txt">https://www.gnu.org/licenses/gpl-2.0.txt</a>
|
||||
for details.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
function selTab(evt, id) {
|
||||
var i, tabcontent, tablinks;
|
||||
|
@ -93,7 +81,7 @@ function selTab(evt, id) {
|
|||
tablinks[i].className = tablinks[i].className.replace(" active", "");
|
||||
}
|
||||
var act = document.getElementById(id);
|
||||
act.style.display = "block";
|
||||
act.style.display = "flex";
|
||||
evt.currentTarget.className += " active";
|
||||
|
||||
var link = act.dataset.src;
|
||||
|
@ -104,6 +92,7 @@ function selTab(evt, id) {
|
|||
}
|
||||
document.getElementById("defaultTab").click();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
let stypes=new Map();
|
||||
stypes.set('4', 'RS41');
|
||||
stypes.set('R', 'RS92');
|
||||
stypes.set('9', 'DFM9 (old)');
|
||||
stypes.set('6', 'DFM6 (old)');
|
||||
stypes.set('D', 'DFM');
|
||||
stypes.set('M', 'M10');
|
||||
stypes.set('2', 'M20');
|
||||
|
||||
/* Used by qrg.html in RX_FSK.ino */
|
||||
function prep() {
|
||||
var stlist=document.querySelectorAll("input.stype");
|
||||
for(txt of stlist){
|
||||
var val=txt.getAttribute('value'); var nam=txt.getAttribute('name');
|
||||
var sel=document.createElement('select');
|
||||
sel.setAttribute('name',nam);
|
||||
for(stype of stypes) {
|
||||
var opt=document.createElement('option');
|
||||
opt.value=stype[0];
|
||||
opt.innerHTML=stype[1];
|
||||
if(stype[0]==val) { opt.setAttribute('selected','selected'); }
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
txt.replaceWith(sel);
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = prep;
|
|
@ -4,6 +4,18 @@ body, html {
|
|||
font-family: Arial;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
}
|
||||
.tci {
|
||||
flex-grow: 1; border: none; margin: 0; padding: 0;
|
||||
}
|
||||
.footer {
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
|
@ -31,7 +43,8 @@ td#sfreq {
|
|||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 14px 16px;
|
||||
padding: 10px 10px;
|
||||
width: 16vw;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
|
@ -42,13 +55,21 @@ td#sfreq {
|
|||
.tab button.active {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
.tabcontent {
|
||||
display: none;
|
||||
flex: 1;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-top: none;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html {
|
||||
|
@ -59,12 +80,12 @@ html {
|
|||
}
|
||||
h1{
|
||||
color: #0F3376;
|
||||
padding: 2vh;
|
||||
font-size: 24px
|
||||
}
|
||||
p{
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.button {
|
||||
.canberemoved_button {
|
||||
display: inline-block;
|
||||
background-color: #008CBA;
|
||||
border: none;
|
||||
|
@ -79,3 +100,31 @@ p{
|
|||
.button2 {
|
||||
background-color: #f44336;
|
||||
}
|
||||
.save {
|
||||
background-color: #0F3376;
|
||||
border: black;
|
||||
border-width: 1;
|
||||
color: white;
|
||||
padding: 8px 30px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
margin: 0
|
||||
}
|
||||
.ctlbtn {
|
||||
background-color: #ccc;
|
||||
border: black;
|
||||
border-width: 1;
|
||||
color: black;
|
||||
padding: 4px 30px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin: 2;
|
||||
font-size: 4vh;
|
||||
}
|
||||
.update {
|
||||
margin: 0;
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const char *version_name = "rdzTTGOsonde";
|
||||
const char *version_id = "devel20210209";
|
||||
const char *version_id = "devel20210213";
|
||||
const int SPIFFS_MAJOR=2;
|
||||
const int SPIFFS_MINOR=9;
|
||||
const int SPIFFS_MINOR=10;
|
||||
|
|
|
@ -357,7 +357,7 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
|||
sonde.si()->dir = dir;
|
||||
Serial.print(" ");
|
||||
sonde.si()->hs = sqrt((float)(vn*vn+ve*ve));
|
||||
Serial.print(sonde.si()->hs);
|
||||
Serial.print(sonde.si()->hs*3.6);
|
||||
Serial.print("km/h ");
|
||||
Serial.print(dir);
|
||||
Serial.print("deg ");
|
||||
|
|
Ładowanie…
Reference in New Issue