Browse Source

reset button, refined css, loader, improved timeout calculation

master
Ondřej Hruška 6 years ago
parent
commit
7a6bdef334
  1. 8
      esp_meas.pro
  2. 2
      esp_meas.pro.user
  3. 2
      html/css/app.css
  4. BIN
      html/img/loader.gif
  5. 6
      html/js/all.js
  6. 14
      html/pages/about.tpl
  7. 14
      html/pages/fft.html
  8. 35
      html/pages/status.tpl
  9. 14
      html/pages/wfm.html
  10. 14
      html/pages/wifi.tpl
  11. 1330
      html_src/css/app.css
  12. 2
      html_src/css/app.css.map
  13. 7
      html_src/js-src/lib/chibi.js
  14. 63
      html_src/js-src/page_waveform.js
  15. 8920
      html_src/js/all.js
  16. 2
      html_src/js/all.js.map
  17. 21
      html_src/page_status.php
  18. 10
      html_src/sass/layout/_modal.scss
  19. 1
      libesphttpd/include/platform.h
  20. 29
      libesphttpd/util/cgiwifi.c
  21. 16
      user/cgi_ping.c
  22. 11
      user/cgi_ping.h
  23. 27
      user/cgi_reset.c
  24. 9
      user/cgi_reset.h
  25. 7
      user/page_waveform.c
  26. 4
      user/routes.c
  27. 7
      user/sampling.c
  28. 4
      user/sampling.h

8
esp_meas.pro

@ -61,7 +61,9 @@ SOURCES += \
user/page_waveform.c \
user/utils.c \
sbmp/library/payload_builder.c \
user/page_about.c
user/page_about.c \
user/cgi_reset.c \
user/cgi_ping.c
HEADERS += \
include/uart_hw.h \
@ -145,7 +147,9 @@ HEADERS += \
user/utils.h \
sbmp/library/payload_builder.h \
user/page_about.h \
user/fw_version.h
user/fw_version.h \
user/cgi_reset.h \
user/cgi_ping.h
DISTFILES += \
style.astylerc \

2
esp_meas.pro.user

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.6.1, 2016-03-31T20:15:31. -->
<!-- Written by QtCreator 3.6.1, 2016-04-01T02:05:29. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

2
html/css/app.css

File diff suppressed because one or more lines are too long

BIN
html/img/loader.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

6
html/js/all.js

File diff suppressed because one or more lines are too long

14
html/pages/about.tpl

@ -5,12 +5,15 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>About - Current analyzer</title>
<title>About - Current Analyser</title>
<link href="/css/app.css" rel="stylesheet">
<script src="/js/all.js"></script>
<script>
// server root (or URL) - used for local development with remote AJAX calls
// (this needs CORS working on the target - which I added to esp-httpd)
var _root = "";
</script>
</head>
<body class="page-about">
<div id="outer">
@ -18,6 +21,7 @@
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div>
<a href="/">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/about" class="selected">About</a></nav>
<div id="content">
<img src="/img/loader.gif" alt="Loading…" id="loader">
<h1>About</h1>
@ -60,7 +64,7 @@
</table>
</div>
</div>
</div>
</div><!-- content -->
</div><!-- outer -->
</body>
</html>

14
html/pages/fft.html

@ -5,12 +5,15 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>FFT - Current analyzer</title>
<title>FFT - Current Analyser</title>
<link href="/css/app.css" rel="stylesheet">
<script src="/js/all.js"></script>
<script>
// server root (or URL) - used for local development with remote AJAX calls
// (this needs CORS working on the target - which I added to esp-httpd)
var _root = "";
</script>
</head>
<body class="page-fft">
<div id="outer">
@ -18,6 +21,7 @@
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div>
<a href="/">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft" class="selected">FFT</a><a href="/about">About</a></nav>
<div id="content">
<img src="/img/loader.gif" alt="Loading…" id="loader">
<h1>FFT</h1>
@ -79,7 +83,7 @@
$().ready(page_waveform.init('fft'));
</script>
</div>
</div>
</div><!-- content -->
</div><!-- outer -->
</body>
</html>

35
html/pages/status.tpl

@ -5,12 +5,15 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Home - Current analyzer</title>
<title>Home - Current Analyser</title>
<link href="/css/app.css" rel="stylesheet">
<script src="/js/all.js"></script>
<script>
// server root (or URL) - used for local development with remote AJAX calls
// (this needs CORS working on the target - which I added to esp-httpd)
var _root = "";
</script>
</head>
<body class="page-home">
<div id="outer">
@ -18,6 +21,7 @@
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div>
<a href="/" class="selected">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/about">About</a></nav>
<div id="content">
<img src="/img/loader.gif" alt="Loading…" id="loader">
<h1>System Status</h1>
@ -32,6 +36,10 @@
<th>Free heap:</th>
<td id="heap">%heap%</td>
</tr>
<tr>
<th></th>
<td><a onclick="trigReset()" class="button btn-red">SW reset</a></td>
</tr>
</table>
</div>
@ -98,11 +106,28 @@
</table>
</div>
<div class="Modal hidden" id="reset-modal">
<div class="Dialog center">
<h2>The device has been reset.</h2>
<p>If you're connected to the AP, you'll have to re-connect.</p>
<p>Please wait a few seconds, then refresh the page.</p>
<p><a onclick="location.reload()" class="button btn-blue">Refresh</a></p>
</div>
</div>
<script>
$().ready(page_status.init);
function trigReset() {
$().get(_root+'/reset.cgi', function(resp, status) {
if (status == 200) {
modal.show('#reset-modal');
}
});
}
</script>
</div>
</div>
</div><!-- content -->
</div><!-- outer -->
</body>
</html>

14
html/pages/wfm.html

@ -5,12 +5,15 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Waveform - Current analyzer</title>
<title>Waveform - Current Analyser</title>
<link href="/css/app.css" rel="stylesheet">
<script src="/js/all.js"></script>
<script>
// server root (or URL) - used for local development with remote AJAX calls
// (this needs CORS working on the target - which I added to esp-httpd)
var _root = "";
</script>
</head>
<body class="page-waveform">
<div id="outer">
@ -18,6 +21,7 @@
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div>
<a href="/">Home</a><a href="/wifi">WiFi config</a><a href="/waveform" class="selected">Waveform</a><a href="/fft">FFT</a><a href="/about">About</a></nav>
<div id="content">
<img src="/img/loader.gif" alt="Loading…" id="loader">
<h1>Waveform</h1>
@ -68,7 +72,7 @@
$().ready(page_waveform.init('raw'));
</script>
</div>
</div>
</div><!-- content -->
</div><!-- outer -->
</body>
</html>

14
html/pages/wifi.tpl

@ -5,12 +5,15 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>WiFi config - Current analyzer</title>
<title>WiFi config - Current Analyser</title>
<link href="/css/app.css" rel="stylesheet">
<script src="/js/all.js"></script>
<script>
// server root (or URL) - used for local development with remote AJAX calls
// (this needs CORS working on the target - which I added to esp-httpd)
var _root = "";
</script>
</head>
<body class="page-wifi">
<div id="outer">
@ -18,6 +21,7 @@
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div>
<a href="/">Home</a><a href="/wifi" class="selected">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/about">About</a></nav>
<div id="content">
<img src="/img/loader.gif" alt="Loading…" id="loader">
<h1>Wireless Setup</h1>
@ -57,7 +61,7 @@
</div>
</div>
</div>
</div>
</div><!-- content -->
</div><!-- outer -->
</body>
</html>

1330
html_src/css/app.css

File diff suppressed because one or more lines are too long

2
html_src/css/app.css.map

File diff suppressed because one or more lines are too long

7
html_src/js-src/lib/chibi.js

@ -616,12 +616,17 @@
// prevent caching
url += (url.indexOf('?') === -1) ? '?' + timestamp : '&' + timestamp;
$('#loader').addClass('show');
// Douglas Crockford: "Synchronous programming is disrespectful and should not be employed in applications which are used by people"
xhr.open(type, url, true);
xhr.timeout = 15000; // a default value. TODO way to set it for the caller
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (callback) {
$('#loader').removeClass('show');
if (callback && xhr.status != 0) { // xhr.status 0 means "aborted"
callback(xhr.responseText, xhr.status);
}
}

63
html_src/js-src/page_waveform.js

@ -137,22 +137,27 @@ var page_waveform = (function () {
readoutPending = false;
if (status != 200) {
if (status != 0) { // 0 = aborted
alert("Request failed.");
}
return;
}
console.error("Request failed.");
var j = JSON.parse(resp);
if (!j.success) {
alert("Sampling failed.");
return;
}
if (autoReload)
toggleAutoReload(); // turn it off.
if (autoReload)
arTimeout = setTimeout(requestReload, autoReloadTime);
} else {
var j = JSON.parse(resp);
if (!j.success) {
console.error("Sampling / readout failed.");
if (autoReload)
toggleAutoReload(); // turn it off.
buildChart(j);
return;
}
buildChart(j);
if (autoReload)
arTimeout = setTimeout(requestReload, autoReloadTime);
}
}
function requestReload() {
@ -171,6 +176,22 @@ var page_waveform = (function () {
return true;
}
function toggleAutoReload() {
autoReloadTime = +$('#ar-time').val() * 1000; // ms
autoReload = !autoReload;
if (autoReload) {
requestReload();
} else {
clearTimeout(arTimeout);
}
$('#ar-btn')
.toggleClass('btn-blue')
.toggleClass('btn-red')
.val(autoReload ? 'Stop' : 'Auto');
}
wfm.init = function (format) {
// --- Load data ---
dataFormat = format;
@ -211,21 +232,7 @@ var page_waveform = (function () {
});
// auto-reload button
$('#ar-btn').on('click', function() {
autoReloadTime = +$('#ar-time').val() * 1000; // ms
autoReload = !autoReload;
if (autoReload) {
requestReload();
} else {
clearTimeout(arTimeout);
}
$('#ar-btn')
.toggleClass('btn-blue')
.toggleClass('btn-red')
.val(autoReload ? 'Stop' : 'Auto');
});
$('#ar-btn').on('click', toggleAutoReload);
};
return wfm;

8920
html_src/js/all.js

File diff suppressed because one or more lines are too long

2
html_src/js/all.js.map

File diff suppressed because one or more lines are too long

21
html_src/page_status.php

@ -13,6 +13,10 @@
<th>Free heap:</th>
<td id="heap">%heap%</td>
</tr>
<tr>
<th></th>
<td><a onclick="trigReset()" class="button btn-red">SW reset</a></td>
</tr>
</table>
</div>
@ -79,8 +83,25 @@
</table>
</div>
<div class="Modal hidden" id="reset-modal">
<div class="Dialog center">
<h2>The device has been reset.</h2>
<p>If you're connected to the AP, you'll have to re-connect.</p>
<p>Please wait a few seconds, then refresh the page.</p>
<p><a onclick="location.reload()" class="button btn-blue">Refresh</a></p>
</div>
</div>
<script>
$().ready(page_status.init);
function trigReset() {
$().get(_root+'/reset.cgi', function(resp, status) {
if (status == 200) {
modal.show('#reset-modal');
}
});
}
</script>
<?php include "_end.php"; ?>

10
html_src/sass/layout/_modal.scss

@ -16,7 +16,7 @@
.Dialog {
margin: dist(-1);
padding: dist(0) dist(-1);
padding: dist(0);
overflow: hidden;
max-width: 100%;
@ -30,4 +30,12 @@
box-shadow: 0 0 2px 0 #434349, 0 0 6px 0 black;
border-radius: 6px;
h1,h2 {
margin-top:0;
}
p:last-child {
margin-bottom: 0;
}
}

1
libesphttpd/include/platform.h

@ -2,7 +2,6 @@
#define PLATFORM_H
#include <osapi.h>
#include "espmissingprotos.h"
#ifdef FREERTOS

29
libesphttpd/util/cgiwifi.c

@ -20,6 +20,24 @@ Cgi/template routines for the /wifi url.
//Enable this to disallow any changes in AP settings
//#define DEMO_MODE
static ETSTimer resetTmr;
void FLASH_FN resetTmrCb(void *arg)
{
system_restart();
}
static void FLASH_FN reset_later(int ms)
{
os_timer_disarm(&resetTmr);
os_timer_setfn(&resetTmr, resetTmrCb, NULL);
os_timer_arm(&resetTmr, ms, false);
}
//WiFi access point data
typedef struct {
char ssid[32];
@ -170,7 +188,7 @@ static struct station_config stconf;
//This routine is ran some time after a connection attempt to an access point. If
//the connect succeeds, this gets the module in STA-only mode.
static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
static void ICACHE_FLASH_ATTR staResetTimerCb(void *arg) {
int x=wifi_station_get_connect_status();
if (x==STATION_GOT_IP) {
//Go to STA mode. This needs a reset, so do that.
@ -200,7 +218,7 @@ static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) {
if (x!=1) {
//Schedule disconnect/connect
os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_setfn(&resetTimer, staResetTimerCb, NULL);
os_timer_arm(&resetTimer, 15000, 0); //time out after 15 secs of trying to connect
}
}
@ -254,7 +272,10 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
info("cgiWifiSetMode: %s", buff);
#ifndef DEMO_MODE
wifi_set_opmode(atoi(buff));
system_restart(); // FIXME we should do this in a timer task, so the browser gets a response.
reset_later(100);
//system_restart(); // FIXME we should do this in a timer task, so the browser gets a response.
#endif
}
httpdRedirect(connData, "/wifi");
@ -279,7 +300,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) {
(info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff);
//Reset into AP-only mode sooner.
os_timer_disarm(&resetTimer);
os_timer_setfn(&resetTimer, resetTimerCb, NULL);
os_timer_setfn(&resetTimer, staResetTimerCb, NULL);
os_timer_arm(&resetTimer, 1000, 0);
} else {
len=sprintf(buff, "{\"status\":\"working\"}");

16
user/cgi_ping.c

@ -0,0 +1,16 @@
#include "cgi_ping.h"
int FLASH_FN cgiPing(HttpdConnData *connData)
{
if (connData->conn==NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
httpdStartResponse(connData, 200);
httpdEndHeaders(connData);
httpdSend(connData, "pong\n", -1);
return HTTPD_CGI_DONE;
}

11
user/cgi_ping.h

@ -0,0 +1,11 @@
#ifndef CGI_PING_H
#define CGI_PING_H
#include <esp8266.h>
#include <httpd.h>
// this is used by the UI to check if server is already restarted and working again.
int cgiPing(HttpdConnData *connData);
#endif // CGI_PING_H

27
user/cgi_reset.c

@ -0,0 +1,27 @@
#include "cgi_reset.h"
static ETSTimer tmr;
static void FLASH_FN tmrCb(void *arg)
{
system_restart();
}
int FLASH_FN cgiResetDevice(HttpdConnData *connData)
{
if (connData->conn==NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
httpdStartResponse(connData, 200);
httpdEndHeaders(connData);
os_timer_disarm(&tmr);
os_timer_setfn(&tmr, tmrCb, NULL);
os_timer_arm(&tmr, 100, false);
httpdSend(connData, "system reset\n", -1);
return HTTPD_CGI_DONE;
}

9
user/cgi_reset.h

@ -0,0 +1,9 @@
#ifndef CGI_RESET_H
#define CGI_RESET_H
#include <esp8266.h>
#include <httpd.h>
int cgiResetDevice(HttpdConnData *connData);
#endif // CGI_RESET_H

7
user/page_waveform.c

@ -14,6 +14,7 @@
typedef struct {
uint16_t total_count;
uint16_t done_count;
uint32_t freq;
bool success;
} tplReadSamplesJSON_state;
@ -73,6 +74,8 @@ static int FLASH_FN tplSamplesJSON(MEAS_FORMAT fmt, HttpdConnData *connData, cha
st->total_count = count;
st->done_count = 0;
st->freq = freq;
// --- REQUEST THE DATA ---
// This actually asks the STM32 over SBMP to start the ADC DMA,
// and we'll wait for the data to arrive.
@ -97,7 +100,9 @@ static int FLASH_FN tplSamplesJSON(MEAS_FORMAT fmt, HttpdConnData *connData, cha
uint16_t chunk_len = 0;
// 10 secs or 100 ms - longer wait for intial data.
for (int i = 0; i < (st->done_count == 0 ? SAMPLING_TMEO*100: SAMP_READOUT_TMEO*100); i++) {
int timeout = (st->done_count == 0 ? (int)meas_estimate_duration(st->total_count, st->freq): SAMP_READOUT_TMEO);
for (int i = 0; i < timeout*100; i++) {
uart_poll();
if (meas_chunk_ready() || meas_is_closed()) break; // We have some data! --- or transaction aborted by peer :(
os_delay_us(10); // 1 ms

4
user/routes.c

@ -13,6 +13,8 @@
#include "page_status.h"
#include "page_waveform.h"
#include "page_about.h"
#include "cgi_reset.h"
#include "cgi_ping.h"
#define WIFI_PROTECT 0
@ -39,6 +41,8 @@ HttpdBuiltInUrl builtInUrls[] = {
// otherwise they're encoded the same like the HTML ones -> no heatshrink, no gzip
// --- UI pages ---
ROUTE_CGI("/reset.cgi", cgiResetDevice),
ROUTE_CGI("/ping.cgi", cgiPing),
// System Status page
ROUTE_TPL_FILE("/", tplSystemStatus, "/pages/status.tpl"),

7
user/sampling.c

@ -37,6 +37,11 @@ bool FLASH_FN meas_is_closed(void)
return !rd.pending;
}
uint32_t FLASH_FN meas_estimate_duration(uint32_t count, uint32_t freq)
{
return (uint32_t)((count*1000.0f) / freq) + 1000;
}
// --- timeout ---
@ -227,7 +232,7 @@ bool FLASH_FN meas_request_data(MEAS_FORMAT format, uint16_t count, uint32_t fre
memset(&rd.stats, 0, sizeof(MeasStats)); // clear the stats obj
// start the abort timer - timeout
setReadoutTmeoTimer(SAMPLING_TMEO);
setReadoutTmeoTimer((int)meas_estimate_duration(count, freq));
// start a message
uint16_t sesn = 0;

4
user/sampling.h

@ -5,7 +5,6 @@
#include <httpd.h>
#include "datalink.h"
#define SAMPLING_TMEO 10000
#define SAMP_READOUT_TMEO 500
typedef struct {
@ -35,6 +34,9 @@ typedef enum {
* Waiting should have a timeout, if data not received, return error status to client.
*/
/** Estimate time needed for sampling (with some space) */
uint32_t meas_estimate_duration(uint32_t count,uint32_t freq);
/** Request data from the sampling module. Count - number of samples. */
bool meas_request_data(MEAS_FORMAT format, uint16_t count, uint32_t freq); // TODO specify what kind of data - currently direct samples.

Loading…
Cancel
Save