web ui usability enhancements

pull/71/head
Hansi, dl9rdz 2021-02-13 12:23:21 +01:00
rodzic 981ecc8044
commit 7db0e8ff11
6 zmienionych plików z 155 dodań i 56 usunięć

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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 &copy; 2019-2020 by Hansi Reiser, DL9RDZ<br>
Copyright &copy; 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>

28
RX_FSK/data/rdz.js 100644
Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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 ");