parent
2357472b4c
commit
f77caa03f2
@ -0,0 +1,161 @@ |
|||||||
|
TEMPLATE = app |
||||||
|
CONFIG += console |
||||||
|
CONFIG -= app_bundle |
||||||
|
CONFIG -= qt |
||||||
|
|
||||||
|
DEFINES = ESPFS_HEATSHRINK HTTPD_MAX_CONNECTIONS=4 __ets__ |
||||||
|
|
||||||
|
INCLUDEPATH = . \ |
||||||
|
esp_iot_sdk_v1.5.2/include \ |
||||||
|
include \ |
||||||
|
user \ |
||||||
|
esphttpclient \ |
||||||
|
libesphttpd/include \ |
||||||
|
libesphttpd/espfs \ |
||||||
|
libesphttpd/core \ |
||||||
|
libesphttpd/lib/heatshrink \ |
||||||
|
sbmp/library \ |
||||||
|
/home/ondra/devel/esp/sdk/esp-open-sdk/xtensa-lx106-elf/xtensa-lx106-elf/include |
||||||
|
|
||||||
|
SOURCES += \ |
||||||
|
libesphttpd/core/auth.c \ |
||||||
|
libesphttpd/core/base64.c \ |
||||||
|
libesphttpd/core/httpd-freertos.c \ |
||||||
|
libesphttpd/core/httpd-nonos.c \ |
||||||
|
libesphttpd/core/httpd.c \ |
||||||
|
libesphttpd/core/httpdespfs.c \ |
||||||
|
libesphttpd/core/sha1.c \ |
||||||
|
libesphttpd/espfs/espfstest/main.c \ |
||||||
|
libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c \ |
||||||
|
libesphttpd/espfs/mkespfsimage/main.c \ |
||||||
|
libesphttpd/espfs/espfs.c \ |
||||||
|
libesphttpd/espfs/heatshrink_decoder.c \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink.c \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink_decoder.c \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink_encoder.c \ |
||||||
|
libesphttpd/lib/heatshrink/test_heatshrink_dynamic.c \ |
||||||
|
libesphttpd/lib/heatshrink/test_heatshrink_dynamic_theft.c \ |
||||||
|
libesphttpd/lib/heatshrink/test_heatshrink_static.c \ |
||||||
|
libesphttpd/mkupgimg/mkupgimg.c \ |
||||||
|
libesphttpd/util/captdns.c \ |
||||||
|
libesphttpd/util/cgiflash.c \ |
||||||
|
libesphttpd/util/cgiwebsocket.c \ |
||||||
|
libesphttpd/util/cgiwifi.c \ |
||||||
|
user/cgi-test.c \ |
||||||
|
user/io.c \ |
||||||
|
user/user_main.c \ |
||||||
|
user/uart_driver.c \ |
||||||
|
sbmp/library/crc32.c \ |
||||||
|
sbmp/library/sbmp_checksum.c \ |
||||||
|
sbmp/library/sbmp_datagram.c \ |
||||||
|
sbmp/library/sbmp_frame.c \ |
||||||
|
sbmp/library/sbmp_session.c \ |
||||||
|
sbmp/library/sbmp_bulk.c \ |
||||||
|
user/datalink.c \ |
||||||
|
user/serial.c \ |
||||||
|
user/uptime.c \ |
||||||
|
sbmp/library/payload_parser.c \ |
||||||
|
user/sampling.c \ |
||||||
|
user/ftoa.c \ |
||||||
|
user/routes.c \ |
||||||
|
user/utils.c \ |
||||||
|
sbmp/library/payload_builder.c \ |
||||||
|
user/cgi_reset.c \ |
||||||
|
user/cgi_ping.c \ |
||||||
|
esphttpclient/test/httpclient_test.c \ |
||||||
|
esphttpclient/httpclient.c \ |
||||||
|
user/wificontrol.c \ |
||||||
|
user/page_home.c \ |
||||||
|
user/pers_cfg.c |
||||||
|
|
||||||
|
HEADERS += \ |
||||||
|
include/uart_hw.h \ |
||||||
|
include/user_config.h \ |
||||||
|
libesphttpd/core/base64.h \ |
||||||
|
libesphttpd/core/httpd-platform.h \ |
||||||
|
libesphttpd/espfs/espfsformat.h \ |
||||||
|
libesphttpd/espfs/heatshrink_config_custom.h \ |
||||||
|
libesphttpd/include/auth.h \ |
||||||
|
libesphttpd/include/captdns.h \ |
||||||
|
libesphttpd/include/cgiflash.h \ |
||||||
|
libesphttpd/include/cgiwebsocket.h \ |
||||||
|
libesphttpd/include/cgiwifi.h \ |
||||||
|
libesphttpd/include/esp8266.h \ |
||||||
|
libesphttpd/include/espfs.h \ |
||||||
|
libesphttpd/include/httpd.h \ |
||||||
|
libesphttpd/include/httpdespfs.h \ |
||||||
|
libesphttpd/include/platform.h \ |
||||||
|
libesphttpd/include/sha1.h \ |
||||||
|
libesphttpd/include/user_config.h \ |
||||||
|
libesphttpd/include/webpages-espfs.h \ |
||||||
|
libesphttpd/lib/heatshrink/greatest.h \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink_common.h \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink_config.h \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink_decoder.h \ |
||||||
|
libesphttpd/lib/heatshrink/heatshrink_encoder.h \ |
||||||
|
user/cgi-test.h \ |
||||||
|
user/io.h \ |
||||||
|
user/uart_register.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/json/json.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/json/jsonparse.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/json/jsontree.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/airkiss.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/at_custom.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/c_types.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/eagle_soc.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/esp_sdk_ver.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/espconn.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/espnow.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/ets_sys.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/gpio.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/ip_addr.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/mem.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/mesh.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/os_type.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/osapi.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/ping.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/pwm.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/queue.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/slc_register.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/smartconfig.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/sntp.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/spi_flash.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/spi_register.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/uart_register.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/upgrade.h \ |
||||||
|
esp_iot_sdk_v1.5.2/include/user_interface.h \ |
||||||
|
user/uart_driver.h \ |
||||||
|
sbmp/library/crc32.h \ |
||||||
|
sbmp/library/sbmp.h \ |
||||||
|
sbmp/library/sbmp_checksum.h \ |
||||||
|
sbmp/library/sbmp_config.h \ |
||||||
|
sbmp/library/sbmp_datagram.h \ |
||||||
|
sbmp/library/sbmp_frame.h \ |
||||||
|
sbmp/library/sbmp_logging.h \ |
||||||
|
sbmp/library/sbmp_session.h \ |
||||||
|
sbmp/library/sbmp_bulk.h \ |
||||||
|
user/datalink.h \ |
||||||
|
user/serial.h \ |
||||||
|
libesphttpd/include/logging.h \ |
||||||
|
user/uptime.h \ |
||||||
|
sbmp/library/payload_parser.h \ |
||||||
|
user/sampling.h \ |
||||||
|
user/sbmp_config.h \ |
||||||
|
sbmp/library/sbmp_config.example.h \ |
||||||
|
user/ftoa.h \ |
||||||
|
user/routes.h \ |
||||||
|
libesphttpd/include/espmissingprotos.h \ |
||||||
|
user/utils.h \ |
||||||
|
sbmp/library/payload_builder.h \ |
||||||
|
user/fw_version.h \ |
||||||
|
user/cgi_reset.h \ |
||||||
|
user/cgi_ping.h \ |
||||||
|
esphttpclient/espmissingincludes.h \ |
||||||
|
esphttpclient/httpclient.h \ |
||||||
|
user/wificontrol.h \ |
||||||
|
user/page_home.h \ |
||||||
|
user/pers_cfg.h |
||||||
|
|
||||||
|
DISTFILES += \ |
||||||
|
style.astylerc \ |
||||||
|
Makefile |
@ -1,167 +0,0 @@ |
|||||||
TEMPLATE = app |
|
||||||
CONFIG += console |
|
||||||
CONFIG -= app_bundle |
|
||||||
CONFIG -= qt |
|
||||||
|
|
||||||
DEFINES = ESPFS_HEATSHRINK HTTPD_MAX_CONNECTIONS=4 __ets__ |
|
||||||
|
|
||||||
INCLUDEPATH = . \ |
|
||||||
esp_iot_sdk_v1.5.2/include \ |
|
||||||
include \ |
|
||||||
user \ |
|
||||||
esphttpclient \ |
|
||||||
libesphttpd/include \ |
|
||||||
libesphttpd/espfs \ |
|
||||||
libesphttpd/core \ |
|
||||||
libesphttpd/lib/heatshrink \ |
|
||||||
sbmp/library \ |
|
||||||
/home/ondra/devel/esp/sdk/esp-open-sdk/xtensa-lx106-elf/xtensa-lx106-elf/include |
|
||||||
|
|
||||||
SOURCES += \ |
|
||||||
libesphttpd/core/auth.c \ |
|
||||||
libesphttpd/core/base64.c \ |
|
||||||
libesphttpd/core/httpd-freertos.c \ |
|
||||||
libesphttpd/core/httpd-nonos.c \ |
|
||||||
libesphttpd/core/httpd.c \ |
|
||||||
libesphttpd/core/httpdespfs.c \ |
|
||||||
libesphttpd/core/sha1.c \ |
|
||||||
libesphttpd/espfs/espfstest/main.c \ |
|
||||||
libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c \ |
|
||||||
libesphttpd/espfs/mkespfsimage/main.c \ |
|
||||||
libesphttpd/espfs/espfs.c \ |
|
||||||
libesphttpd/espfs/heatshrink_decoder.c \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink.c \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink_decoder.c \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink_encoder.c \ |
|
||||||
libesphttpd/lib/heatshrink/test_heatshrink_dynamic.c \ |
|
||||||
libesphttpd/lib/heatshrink/test_heatshrink_dynamic_theft.c \ |
|
||||||
libesphttpd/lib/heatshrink/test_heatshrink_static.c \ |
|
||||||
libesphttpd/mkupgimg/mkupgimg.c \ |
|
||||||
libesphttpd/util/captdns.c \ |
|
||||||
libesphttpd/util/cgiflash.c \ |
|
||||||
libesphttpd/util/cgiwebsocket.c \ |
|
||||||
libesphttpd/util/cgiwifi.c \ |
|
||||||
user/cgi-test.c \ |
|
||||||
user/io.c \ |
|
||||||
user/user_main.c \ |
|
||||||
user/uart_driver.c \ |
|
||||||
sbmp/library/crc32.c \ |
|
||||||
sbmp/library/sbmp_checksum.c \ |
|
||||||
sbmp/library/sbmp_datagram.c \ |
|
||||||
sbmp/library/sbmp_frame.c \ |
|
||||||
sbmp/library/sbmp_session.c \ |
|
||||||
sbmp/library/sbmp_bulk.c \ |
|
||||||
user/datalink.c \ |
|
||||||
user/serial.c \ |
|
||||||
user/uptime.c \ |
|
||||||
sbmp/library/payload_parser.c \ |
|
||||||
user/sampling.c \ |
|
||||||
user/ftoa.c \ |
|
||||||
user/routes.c \ |
|
||||||
user/page_status.c \ |
|
||||||
user/page_waveform.c \ |
|
||||||
user/utils.c \ |
|
||||||
sbmp/library/payload_builder.c \ |
|
||||||
user/page_about.c \ |
|
||||||
user/cgi_reset.c \ |
|
||||||
user/cgi_ping.c \ |
|
||||||
esphttpclient/test/httpclient_test.c \ |
|
||||||
esphttpclient/httpclient.c \ |
|
||||||
user/page_monitoring.c \ |
|
||||||
user/reporting.c \ |
|
||||||
user/wificontrol.c |
|
||||||
|
|
||||||
HEADERS += \ |
|
||||||
include/uart_hw.h \ |
|
||||||
include/user_config.h \ |
|
||||||
libesphttpd/core/base64.h \ |
|
||||||
libesphttpd/core/httpd-platform.h \ |
|
||||||
libesphttpd/espfs/espfsformat.h \ |
|
||||||
libesphttpd/espfs/heatshrink_config_custom.h \ |
|
||||||
libesphttpd/include/auth.h \ |
|
||||||
libesphttpd/include/captdns.h \ |
|
||||||
libesphttpd/include/cgiflash.h \ |
|
||||||
libesphttpd/include/cgiwebsocket.h \ |
|
||||||
libesphttpd/include/cgiwifi.h \ |
|
||||||
libesphttpd/include/esp8266.h \ |
|
||||||
libesphttpd/include/espfs.h \ |
|
||||||
libesphttpd/include/httpd.h \ |
|
||||||
libesphttpd/include/httpdespfs.h \ |
|
||||||
libesphttpd/include/platform.h \ |
|
||||||
libesphttpd/include/sha1.h \ |
|
||||||
libesphttpd/include/user_config.h \ |
|
||||||
libesphttpd/include/webpages-espfs.h \ |
|
||||||
libesphttpd/lib/heatshrink/greatest.h \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink_common.h \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink_config.h \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink_decoder.h \ |
|
||||||
libesphttpd/lib/heatshrink/heatshrink_encoder.h \ |
|
||||||
user/cgi-test.h \ |
|
||||||
user/io.h \ |
|
||||||
user/uart_register.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/json/json.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/json/jsonparse.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/json/jsontree.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/airkiss.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/at_custom.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/c_types.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/eagle_soc.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/esp_sdk_ver.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/espconn.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/espnow.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/ets_sys.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/gpio.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/ip_addr.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/mem.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/mesh.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/os_type.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/osapi.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/ping.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/pwm.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/queue.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/slc_register.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/smartconfig.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/sntp.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/spi_flash.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/spi_register.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/uart_register.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/upgrade.h \ |
|
||||||
esp_iot_sdk_v1.5.2/include/user_interface.h \ |
|
||||||
user/uart_driver.h \ |
|
||||||
sbmp/library/crc32.h \ |
|
||||||
sbmp/library/sbmp.h \ |
|
||||||
sbmp/library/sbmp_checksum.h \ |
|
||||||
sbmp/library/sbmp_config.h \ |
|
||||||
sbmp/library/sbmp_datagram.h \ |
|
||||||
sbmp/library/sbmp_frame.h \ |
|
||||||
sbmp/library/sbmp_logging.h \ |
|
||||||
sbmp/library/sbmp_session.h \ |
|
||||||
sbmp/library/sbmp_bulk.h \ |
|
||||||
user/datalink.h \ |
|
||||||
user/serial.h \ |
|
||||||
libesphttpd/include/logging.h \ |
|
||||||
user/uptime.h \ |
|
||||||
sbmp/library/payload_parser.h \ |
|
||||||
user/sampling.h \ |
|
||||||
user/sbmp_config.h \ |
|
||||||
sbmp/library/sbmp_config.example.h \ |
|
||||||
user/ftoa.h \ |
|
||||||
user/routes.h \ |
|
||||||
user/page_status.h \ |
|
||||||
user/page_waveform.h \ |
|
||||||
libesphttpd/include/espmissingprotos.h \ |
|
||||||
user/utils.h \ |
|
||||||
sbmp/library/payload_builder.h \ |
|
||||||
user/page_about.h \ |
|
||||||
user/fw_version.h \ |
|
||||||
user/cgi_reset.h \ |
|
||||||
user/cgi_ping.h \ |
|
||||||
esphttpclient/espmissingincludes.h \ |
|
||||||
esphttpclient/httpclient.h \ |
|
||||||
user/page_monitoring.h \ |
|
||||||
user/reporting.h \ |
|
||||||
user/wificontrol.h |
|
||||||
|
|
||||||
DISTFILES += \ |
|
||||||
style.astylerc \ |
|
||||||
Makefile |
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,77 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<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 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"> |
|
||||||
<nav id="menu"> |
|
||||||
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div> |
|
||||||
<a href="/status">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/spectrogram">Spectrogram</a><a href="/monitoring">Monitoring</a><a href="/about" class="selected">About</a></nav> |
|
||||||
<div id="content"> |
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
|
||||||
|
|
||||||
<h1>About</h1> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<img src="/img/cvut.svg" id="logo" class="mq-tablet-min"> |
|
||||||
<h2>Current Analyser</h2> |
|
||||||
|
|
||||||
<img src="/img/cvut.svg" id="logo2" class="mq-phone"> |
|
||||||
|
|
||||||
<p>© Ondřej Hruška, 2016 <<a href="mailto:ondra@ondrovo.com" target="blank">ondra@ondrovo.com</a>></p> |
|
||||||
|
|
||||||
<p><a href="http://measure.feld.cvut.cz/" target="blank">Katedra měření, FEL ČVUT</a><br>Department of Measurement, FEE CTU</p> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Firmware</h2> |
|
||||||
|
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Firmware</th> |
|
||||||
<td>v%vers_fw%, build <i>%date%</i> at <i>%time%</i></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>esp-httpd lib</th> |
|
||||||
<td>v%vers_httpd%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>SBMP lib</th> |
|
||||||
<td>v%vers_sbmp%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>ESP IoT SDK</th> |
|
||||||
<td>v%vers_sdk%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>STM32 firmware</th> |
|
||||||
<td>v%vers_stm%</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
|
|
||||||
<p> |
|
||||||
The webserver was built using the great <a href="https://github.com/Spritetm/esphttpd" target="blank">esp-httpd</a> |
|
||||||
library by Jeroen Domburg. |
|
||||||
</p> |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div> |
|
||||||
|
|
||||||
</div><!-- content --> |
|
||||||
</div><!-- outer --> |
|
||||||
</body> |
|
||||||
</html> |
|
@ -1,102 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<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 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"> |
|
||||||
<nav id="menu"> |
|
||||||
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div> |
|
||||||
<a href="/status">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft" class="selected">FFT</a><a href="/spectrogram">Spectrogram</a><a href="/monitoring">Monitoring</a><a href="/about">About</a></nav> |
|
||||||
<div id="content"> |
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
|
||||||
|
|
||||||
<h1>FFT</h1> |
|
||||||
|
|
||||||
<div class="Box center" id="samp-ctrl"> |
|
||||||
<div> |
|
||||||
<label for="count">Bins</label> |
|
||||||
<label for="count" class="select-wrap"> |
|
||||||
<select name="count" id="count"> |
|
||||||
<option value="16">8 |
|
||||||
<option value="32">16 |
|
||||||
<option value="64">32 |
|
||||||
<option value="128">64 |
|
||||||
<option value="256">128 |
|
||||||
<option value="512">256 |
|
||||||
<option value="1024">512 |
|
||||||
<option value="2048" selected>1024 |
|
||||||
</select> |
|
||||||
</label> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="freq">f<sub>bw</sub> <span class="mq-normal-min nb">=</span><span class="mq-tablet-max nb">(Hz)</span></label> |
|
||||||
<input id="freq" type="number" value="2048"> |
|
||||||
<span class="mq-normal-min">Hz</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<a id="load" class="button btn-green">Load</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box medium chartbox"> |
|
||||||
<div id="chart" class="ct-chart ct-wide ct-with-area"></div> |
|
||||||
<div class="stats invis"> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Samples</th> |
|
||||||
<td id="stat-count"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>f<sub>s</sub></th> |
|
||||||
<td id="stat-f-s"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>peak</sub></th> |
|
||||||
<td id="stat-i-peak"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>RMS</sub></th> |
|
||||||
<td id="stat-i-rms"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
<div class="ar"><!-- auto reload --> |
|
||||||
<input type="number" id="ar-time" step="100" value="1000" min="0"> ms |
|
||||||
<input type="button" id="ar-btn" class="btn-blue narrow" value="Auto"> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box chartexport hidden"> |
|
||||||
Copy: |
|
||||||
<a data-sep="space">1·2·3</a> |
|
||||||
<a data-sep="comma">1,2,3</a> |
|
||||||
<a data-sep="newline">1↵2↵3</a> |
|
||||||
<a data-sep="csv">CSV</a> |
|
||||||
<br> |
|
||||||
<textarea id="copybox" class="hidden" readonly onfocus="this.select();" onmouseup="return false"></textarea> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_waveform.init('fft')); |
|
||||||
</script> |
|
||||||
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div> |
|
||||||
|
|
||||||
</div><!-- content --> |
|
||||||
</div><!-- outer --> |
|
||||||
</body> |
|
||||||
</html> |
|
@ -0,0 +1,49 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<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 - WiFi Demo</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"> |
||||||
|
<nav id="menu"> |
||||||
|
<div id="brand" onclick="$('#menu').toggleClass('expanded')">WiFi Demo</div> |
||||||
|
<a href="/home" class="selected">Home</a><a href="/wifi">WiFi config</a></nav> |
||||||
|
<div id="content"> |
||||||
|
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
||||||
|
|
||||||
|
<h1>Home</h1> |
||||||
|
|
||||||
|
<div class="Box"> |
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus cum eius molestias nesciunt nihil sequi? Laboriosam molestiae nesciunt |
||||||
|
quis! Aut eius esse in laudantium obcaecati possimus quis repudiandae tenetur velit.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="Box"> |
||||||
|
<h2>Firmware</h2> |
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus cum eius molestias nesciunt nihil sequi? Laboriosam molestiae nesciunt |
||||||
|
quis! Aut eius esse in laudantium obcaecati possimus quis repudiandae tenetur velit.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script> |
||||||
|
$().ready(page_home.init); |
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
<div class="NotifyMsg hidden" id="notif"></div> |
||||||
|
|
||||||
|
</div><!-- content --> |
||||||
|
</div><!-- outer --> |
||||||
|
</body> |
||||||
|
</html> |
@ -1,102 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
|
||||||
|
|
||||||
<title>Monitoring - 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-monitoring"> |
|
||||||
<div id="outer"> |
|
||||||
<nav id="menu"> |
|
||||||
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div> |
|
||||||
<a href="/status">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/spectrogram">Spectrogram</a><a href="/monitoring" class="selected">Monitoring</a><a href="/about">About</a></nav> |
|
||||||
<div id="content"> |
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
|
||||||
|
|
||||||
<h1>Monitoring & Reporting</h1> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Status</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Reference:</th> |
|
||||||
<td> |
|
||||||
<span id="hasref" class="Valfield">%refStored%</span> |
|
||||||
<a onclick="page_mon.captureRef()" class="button btn-green">Capture</a> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Status:</th> |
|
||||||
<td> |
|
||||||
<span class="Valfield" style="vertical-align:middle;"> |
|
||||||
Δ = <span id="actual-dev">%curDeviation%</span><br> |
|
||||||
I<sub>RMS</sub> = <span id="actual-rms">%curRMS%</span> mA |
|
||||||
</span> |
|
||||||
<a onclick="page_mon.compareNow()" class="button btn-blue">Measure</a> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Reporting</h2> |
|
||||||
<form action="/mon/config" method="POST"> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th><label for="rep-on">Reporting:</label></th> |
|
||||||
<td> |
|
||||||
<input type="checkbox" id="rep-on" name="enabled" value="1" %rep_en%><!-- |
|
||||||
--> <label for="rep-on">enabled</label> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th><label for="rep-interval">Interval:</label></th> |
|
||||||
<td> |
|
||||||
<input type="number" name="interval" id="rep-interval" style="max-width: 10em" value="%repInterval%"><!-- |
|
||||||
--> seconds |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Service:</th> |
|
||||||
<td> |
|
||||||
<input type="radio" name="service" value="xv" id="rep-svc-xv" %svc_xv%> <label for="rep-svc-xv">Xively</label> |
|
||||||
<input type="radio" name="service" value="ts" id="rep-svc-ts" %svc_ts%> <label for="rep-svc-ts">ThingSpeak</label> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th><label for="rep-key">API key:</label></th> |
|
||||||
<td><input type="text" name="key" id="rep-key" value="%repKey%"></td> |
|
||||||
</tr> |
|
||||||
<tr class="xv-only"> |
|
||||||
<th><label for="rep-feed">Feed ID:</label></th> |
|
||||||
<td><input type="text" name="feed" id="rep-feed" value="%repFeed%"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th> </th> |
|
||||||
<td><input type="submit" value="Save changes"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_mon.init); |
|
||||||
</script> |
|
||||||
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div> |
|
||||||
|
|
||||||
</div><!-- content --> |
|
||||||
</div><!-- outer --> |
|
||||||
</body> |
|
||||||
</html> |
|
@ -1,79 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
|
||||||
|
|
||||||
<title>Spectrogram - 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-spectrogram"> |
|
||||||
<div id="outer"> |
|
||||||
<nav id="menu"> |
|
||||||
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div> |
|
||||||
<a href="/status">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/spectrogram" class="selected">Spectrogram</a><a href="/monitoring">Monitoring</a><a href="/about">About</a></nav> |
|
||||||
<div id="content"> |
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
|
||||||
|
|
||||||
<h1>Spectrogram</h1> |
|
||||||
|
|
||||||
<div class="Box center" id="samp-ctrl"> |
|
||||||
<div> |
|
||||||
<label for="count">Bins</label> |
|
||||||
<label for="count" class="select-wrap"> |
|
||||||
<select name="count" id="count"> |
|
||||||
<option value="16">8 |
|
||||||
<option value="32">16 |
|
||||||
<option value="64">32 |
|
||||||
<option value="128">64 |
|
||||||
<option value="256">128 |
|
||||||
<option value="512">256 |
|
||||||
<option value="1024" selected>512 |
|
||||||
<option value="2048">1024 |
|
||||||
</select> |
|
||||||
</label> |
|
||||||
</div> |
|
||||||
<div id="tile-cfg"> |
|
||||||
<label for="tile-x">Tile</label> |
|
||||||
<input id="tile-x" type="number" min=1 step=1 value=4> |
|
||||||
× |
|
||||||
<input id="tile-y" type="number" min=1 step=1 value=1> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="freq">f<sub>bw</sub> <span class="mq-normal-min nb">=</span><span class="mq-tablet-max nb">(Hz)</span></label> |
|
||||||
<input id="freq" type="number" value="2048"> |
|
||||||
<span class="mq-normal-min">Hz</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="interval">Interval <span class="mq-tablet-max" style="font-weight:normal;">(ms)</span></label> |
|
||||||
<input id="interval" type="number" value="0" step=100 min=0> |
|
||||||
<span class="mq-normal-min">ms</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<a id="go-btn" class="button btn-green">Start</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box center"> |
|
||||||
<canvas id="sg" width=860 height=530></canvas> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_spectrogram.init()); |
|
||||||
</script> |
|
||||||
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div> |
|
||||||
|
|
||||||
</div><!-- content --> |
|
||||||
</div><!-- outer --> |
|
||||||
</body> |
|
||||||
</html> |
|
@ -1,128 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<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 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"> |
|
||||||
<nav id="menu"> |
|
||||||
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div> |
|
||||||
<a href="/status" class="selected">Home</a><a href="/wifi">WiFi config</a><a href="/waveform">Waveform</a><a href="/fft">FFT</a><a href="/spectrogram">Spectrogram</a><a href="/monitoring">Monitoring</a><a href="/about">About</a></nav> |
|
||||||
<div id="content"> |
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
|
||||||
|
|
||||||
<h1>System Status</h1> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Runtime</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Uptime:</th> |
|
||||||
<td id="uptime">%uptime%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Free heap:</th> |
|
||||||
<td id="heap">%heap%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th></th> |
|
||||||
<td><a onclick="page_status.trigReset()" class="button btn-red">Restart system</a></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>WiFi</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>WiFi mode:</th> |
|
||||||
<td id="wmode">%wifiMode%</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<!-- WiFi info is read & updated using AJAX --> |
|
||||||
|
|
||||||
<div class="Box sta-only" style="display:none"> |
|
||||||
<h2>WiFi Station</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>SSID:</th> |
|
||||||
<td id="staSSID"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>RSSI:</th> |
|
||||||
<td> |
|
||||||
<span id="staRSSIperc"></span>, |
|
||||||
<span id="staRSSI"></span> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>MAC:</th> |
|
||||||
<td id="staMAC"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box ap-only" style="display:none"> |
|
||||||
<h2>WiFi AP</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>SSID:</th> |
|
||||||
<td id="apSSID"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Hidden:</th> |
|
||||||
<td id="apHidden"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Auth. mode:</th> |
|
||||||
<td id="apAuth"></td> |
|
||||||
</tr> |
|
||||||
<tr class="ap-auth-only"> |
|
||||||
<th>Password:</th> |
|
||||||
<td id="apPwd"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Channel:</th> |
|
||||||
<td id="apChan"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>MAC:</th> |
|
||||||
<td id="apMAC"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Modal hidden no-close" id="reset-modal"> |
|
||||||
<div class="Dialog center"> |
|
||||||
<h2>The device has been reset.</h2> |
|
||||||
<p class="ap-only">If you're connected to the AP, you'll have to re-connect.</p> |
|
||||||
<p>This dialog should close when the restart is complete, please wait around 15 seconds..</p> |
|
||||||
<p><a onclick="location.reload()" class="button btn-blue">Reload the page</a></p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_status.init); |
|
||||||
</script> |
|
||||||
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div> |
|
||||||
|
|
||||||
</div><!-- content --> |
|
||||||
</div><!-- outer --> |
|
||||||
</body> |
|
||||||
</html> |
|
@ -1,91 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8"> |
|
||||||
<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 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"> |
|
||||||
<nav id="menu"> |
|
||||||
<div id="brand" onclick="$('#menu').toggleClass('expanded')">Current Analyser</div> |
|
||||||
<a href="/status">Home</a><a href="/wifi">WiFi config</a><a href="/waveform" class="selected">Waveform</a><a href="/fft">FFT</a><a href="/spectrogram">Spectrogram</a><a href="/monitoring">Monitoring</a><a href="/about">About</a></nav> |
|
||||||
<div id="content"> |
|
||||||
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
|
||||||
|
|
||||||
<h1>Waveform</h1> |
|
||||||
|
|
||||||
<div class="Box center" id="samp-ctrl"> |
|
||||||
<div> |
|
||||||
<label for="count">Samples</label> |
|
||||||
<input id="count" type="number" value="500"> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="freq">f<sub>s</sub> <span class="mq-normal-min nb">=</span><span class="mq-tablet-max nb">(Hz)</span></label> |
|
||||||
<input id="freq" type="number" value="2048"> |
|
||||||
<span class="mq-normal-min">Hz</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<a id="load" class="button btn-green">Load</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box medium chartbox"> |
|
||||||
<div id="chart" class="ct-chart ct-wide"></div> |
|
||||||
<div class="stats invis"> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Samples</th> |
|
||||||
<td id="stat-count"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>f<sub>s</sub></th> |
|
||||||
<td id="stat-f-s"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>peak</sub></th> |
|
||||||
<td id="stat-i-peak"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>RMS</sub></th> |
|
||||||
<td id="stat-i-rms"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
<div class="ar"><!-- auto reload --> |
|
||||||
<input type="number" id="ar-time" step="100" value="1000" min="0"> ms |
|
||||||
<input type="button" id="ar-btn" class="btn-blue narrow" value="Auto"> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box chartexport hidden"> |
|
||||||
Copy: |
|
||||||
<a data-sep="space">1·2·3</a> |
|
||||||
<a data-sep="comma">1,2,3</a> |
|
||||||
<a data-sep="newline">1↵2↵3</a> |
|
||||||
<a data-sep="csv">CSV</a> |
|
||||||
<br> |
|
||||||
<textarea id="copybox" class="hidden" readonly onfocus="this.select();" onmouseup="return false"></textarea> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_waveform.init('raw')); |
|
||||||
</script> |
|
||||||
|
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div> |
|
||||||
|
|
||||||
</div><!-- content --> |
|
||||||
</div><!-- outer --> |
|
||||||
</body> |
|
||||||
</html> |
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,11 @@ |
|||||||
|
/** Wifi page */ |
||||||
|
var page_home = (function () { |
||||||
|
var home = {}; |
||||||
|
|
||||||
|
/** Set up the Home page */ |
||||||
|
home.init = function () { |
||||||
|
//
|
||||||
|
}; |
||||||
|
|
||||||
|
return home; |
||||||
|
})(); |
@ -1,91 +0,0 @@ |
|||||||
var page_mon = (function() { |
|
||||||
var mon = {}; |
|
||||||
|
|
||||||
function updRefInfoField(ok) { |
|
||||||
$('#hasref').html(ok ? 'OK' : 'Not set!'); |
|
||||||
} |
|
||||||
|
|
||||||
/** Capture reference & save to flash */ |
|
||||||
mon.captureRef = function() { |
|
||||||
$().get(_root + '/mon/setref', function(resp, status) { |
|
||||||
if (status != 200) { |
|
||||||
// bad response
|
|
||||||
errorMsg('Operation failed.'); |
|
||||||
} else { |
|
||||||
try { |
|
||||||
// OK
|
|
||||||
var j = JSON.parse(resp); |
|
||||||
updRefInfoField(j.success); |
|
||||||
} catch(e) { |
|
||||||
errorMsg(e); |
|
||||||
updRefInfoField(false); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
/** Capture waveform and compare with reference */ |
|
||||||
mon.compareNow = function() { |
|
||||||
$().get(_root + '/mon/compare', function(resp, status) { |
|
||||||
if (status != 200) { |
|
||||||
// bad response
|
|
||||||
errorMsg('Operation failed.'); |
|
||||||
} else { |
|
||||||
try { |
|
||||||
// OK
|
|
||||||
var j = JSON.parse(resp); |
|
||||||
if (j.success) { |
|
||||||
$('#actual-dev').html(numfmt(j.deviation, 2)); |
|
||||||
$('#actual-rms').html(numfmt(j.rms, 2)); |
|
||||||
} else { |
|
||||||
throw 'Capture failed.'; |
|
||||||
} |
|
||||||
} catch(e) { |
|
||||||
errorMsg(e); |
|
||||||
$('#actual-dev').html('--'); |
|
||||||
$('#actual-rms').html('--'); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
function updateXvOnly() { |
|
||||||
// is xively
|
|
||||||
var isXv = $('#rep-svc-xv')[0].checked; |
|
||||||
|
|
||||||
if (isXv) { |
|
||||||
$('.xv-only').removeClass('hidden'); |
|
||||||
} else { |
|
||||||
$('.xv-only').addClass('hidden'); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
mon.init = function() { |
|
||||||
updateXvOnly(); |
|
||||||
|
|
||||||
$('#rep-svc-xv,#rep-svc-ts').on('change', updateXvOnly); |
|
||||||
|
|
||||||
setInterval(function() { |
|
||||||
$().get(_root + '/mon/status', function(resp, status) { |
|
||||||
if (status == 200) { |
|
||||||
try { |
|
||||||
// OK
|
|
||||||
var j = JSON.parse(resp); |
|
||||||
if (j.success) { |
|
||||||
$('#actual-dev').html(numfmt(j.deviation, 2)); |
|
||||||
$('#actual-rms').html(numfmt(j.rms, 2)); |
|
||||||
} else { |
|
||||||
console.error('Capture failed.'); |
|
||||||
} |
|
||||||
} catch(e) { |
|
||||||
errorMsg(e); |
|
||||||
$('#actual-dev').html('--'); |
|
||||||
$('#actual-rms').html('--'); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
}, 10000); |
|
||||||
}; |
|
||||||
|
|
||||||
return mon; |
|
||||||
})(); |
|
@ -1,356 +0,0 @@ |
|||||||
var page_spectrogram = (function () { |
|
||||||
var sg = {}; |
|
||||||
|
|
||||||
var ctx; |
|
||||||
|
|
||||||
// drawing area
|
|
||||||
var plot = { |
|
||||||
x:50, |
|
||||||
y:10, |
|
||||||
w:740,//860 total
|
|
||||||
h:512, |
|
||||||
dx: 1, // bin
|
|
||||||
dy: 1 |
|
||||||
}; |
|
||||||
|
|
||||||
var opts = { |
|
||||||
interval: 0, |
|
||||||
sampCount: 0, |
|
||||||
freq:0 |
|
||||||
}; |
|
||||||
|
|
||||||
var interval = 1000; |
|
||||||
var running = false; |
|
||||||
var readTimeout; // timer
|
|
||||||
var readoutPending; |
|
||||||
var readXhr; |
|
||||||
|
|
||||||
var lastLoadMs; |
|
||||||
var lastMarkMs; |
|
||||||
var lastMark10s; |
|
||||||
|
|
||||||
var colormap = [ |
|
||||||
/* [val, r, g, b] */ |
|
||||||
[0.00, 0, 0, 0], |
|
||||||
[0.10, 41, 17, 41], |
|
||||||
[0.25, 34, 17, 78], |
|
||||||
[0.6, 17, 30, 105], |
|
||||||
[1.0, 17, 57, 126], |
|
||||||
[1.2, 17, 84, 128], |
|
||||||
[1.3, 17, 111, 115], |
|
||||||
[1.4, 17, 134, 96], |
|
||||||
[1.5, 17, 155, 71], |
|
||||||
[1.6, 68, 194, 17], |
|
||||||
[1.75, 111, 209, 17], |
|
||||||
[1.84, 180, 213, 17], |
|
||||||
[1.90, 223, 217, 86], |
|
||||||
[1.97, 248, 222, 176], |
|
||||||
[1.99, 255, 237, 222], |
|
||||||
[2.00, 255, 255, 255], |
|
||||||
]; |
|
||||||
|
|
||||||
function val2color(val) { |
|
||||||
var x1, x2, c1, c2; |
|
||||||
|
|
||||||
val = Math.log10(1+val); |
|
||||||
|
|
||||||
if (val > 2) val = 2; |
|
||||||
if (val < 0) val = 0; |
|
||||||
|
|
||||||
for (var i = 0; i < colormap.length; i++) { |
|
||||||
var c = colormap[i]; |
|
||||||
var point = c[0]; |
|
||||||
if (val >= point) { |
|
||||||
x1 = point; |
|
||||||
c1 = c; |
|
||||||
} |
|
||||||
|
|
||||||
if (val <= point) { |
|
||||||
x2 = point; |
|
||||||
c2 = c; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
var rate = ((val - x1)/(x2 - x1)); |
|
||||||
if (x1 == x2) rate=0; |
|
||||||
|
|
||||||
var r = Math.round((c1[1] + (c2[1] - c1[1])*rate)); |
|
||||||
var g = Math.round((c1[2] + (c2[2] - c1[2])*rate)); |
|
||||||
var b = Math.round((c1[3] + (c2[3] - c1[3])*rate)); |
|
||||||
return 'rgb('+r+','+g+','+b+')'; |
|
||||||
} |
|
||||||
|
|
||||||
function shiftSg() { |
|
||||||
var imageData = ctx.getImageData(plot.x+plot.dx, plot.y, plot.w-plot.dx, plot.h+10); |
|
||||||
|
|
||||||
ctx.fillStyle = 'black'; |
|
||||||
ctx.fillRect(plot.x, plot.y, plot.w, plot.h); |
|
||||||
ctx.clearRect(plot.x, plot.y+plot.h+1, plot.w, 10); // clear the second marks box
|
|
||||||
|
|
||||||
ctx.putImageData(imageData, plot.x, plot.y); |
|
||||||
} |
|
||||||
|
|
||||||
function drawSg(col) { |
|
||||||
shiftSg(); |
|
||||||
|
|
||||||
var bc = opts.sampCount/2; |
|
||||||
for (var i = 0; i < bc; i++) { |
|
||||||
// resolve color from the value
|
|
||||||
var clr; |
|
||||||
|
|
||||||
if (i*plot.dy > plot.h) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
if (i > col.length) { |
|
||||||
clr = '#000'; |
|
||||||
} else { |
|
||||||
clr = val2color(col[i]); |
|
||||||
} |
|
||||||
ctx.fillStyle = clr; |
|
||||||
|
|
||||||
var tx = plot.x+plot.w-plot.dx; |
|
||||||
var ty = plot.y+plot.h-(i+1)*plot.dy; |
|
||||||
var tw = plot.dx; |
|
||||||
var th = plot.dy; |
|
||||||
|
|
||||||
if (ty<plot.y) { |
|
||||||
th -= plot.y-ty; |
|
||||||
ty = plot.y; |
|
||||||
} |
|
||||||
|
|
||||||
ctx.fillRect(tx, ty, tw, th); |
|
||||||
} |
|
||||||
|
|
||||||
// mark every 10 s
|
|
||||||
//console.log('remain',msElapsed(lastMarkMs));
|
|
||||||
if (msElapsed(lastMarkMs) >= 950) { |
|
||||||
lastMarkMs = msNow(); |
|
||||||
|
|
||||||
var long = false; |
|
||||||
if (msElapsed(lastMark10s) > 9500) { |
|
||||||
long = true; |
|
||||||
lastMark10s = msNow(); |
|
||||||
} |
|
||||||
|
|
||||||
ctx.strokeStyle = 'white'; |
|
||||||
ctx.beginPath(); |
|
||||||
ctx.moveTo(plot.x+plot.w-.5, plot.y+plot.h+1); |
|
||||||
ctx.lineTo(plot.x+plot.w-.5, plot.y+plot.h+1+(long?6:2)); |
|
||||||
ctx.stroke(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
function onRxData(resp, status) { |
|
||||||
readoutPending = false; |
|
||||||
if (status == 200) { |
|
||||||
try { |
|
||||||
var j = JSON.parse(resp); |
|
||||||
if (j.success) { |
|
||||||
// display
|
|
||||||
drawSg(j.samples); |
|
||||||
} else { |
|
||||||
errorMsg("Sampling failed.", 1000); |
|
||||||
} |
|
||||||
} catch(e) { |
|
||||||
errorMsg(e); |
|
||||||
} |
|
||||||
} else { |
|
||||||
errorMsg("Request failed.", 1000); |
|
||||||
} |
|
||||||
|
|
||||||
if (running) |
|
||||||
readTimeout = setTimeout(requestData, Math.max(0, opts.interval - msElapsed(lastLoadMs))); // TODO should actually compute time remaining, this adds interval to the request time.
|
|
||||||
} |
|
||||||
|
|
||||||
function requestData() { |
|
||||||
if (readoutPending) { |
|
||||||
errorMsg("Request already pending - aborting."); |
|
||||||
readXhr.abort(); |
|
||||||
} |
|
||||||
readoutPending = true; |
|
||||||
lastLoadMs = msNow(); |
|
||||||
|
|
||||||
var fs = opts.freq; |
|
||||||
var n = opts.sampCount; |
|
||||||
var url = _root+'/measure/fft?n='+n+'&fs='+fs; |
|
||||||
|
|
||||||
readXhr = $().get(url, onRxData, estimateLoadTime(fs,n)); |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
function drawLegend() { |
|
||||||
var gap = 8; |
|
||||||
var barW = 10; |
|
||||||
var barH = plot.h-12; |
|
||||||
var barY = plot.y+6; |
|
||||||
var barX = plot.x - gap - barW; |
|
||||||
var vStep = (100 / barH); |
|
||||||
for (var i = 0; i < barH; i++) { |
|
||||||
var c1 = val2color(i * vStep); |
|
||||||
var c2 = val2color((i + 1) * vStep); |
|
||||||
|
|
||||||
var y = Math.floor(barY + barH - (i + 1)); |
|
||||||
|
|
||||||
var gradient = ctx.createLinearGradient(0, y + 1, 0, y); |
|
||||||
gradient.addColorStop(0, c1); |
|
||||||
gradient.addColorStop(1, c2); |
|
||||||
ctx.fillStyle = gradient; |
|
||||||
|
|
||||||
ctx.fillRect(barX, y, barW, 1); |
|
||||||
} |
|
||||||
|
|
||||||
// border
|
|
||||||
ctx.strokeStyle = '#000'; |
|
||||||
ctx.strokeRect(barX-.5, barY-.5, barW+1, barH+1); |
|
||||||
|
|
||||||
vStep = (100 / barH); |
|
||||||
ctx.font = '12px sans-serif'; |
|
||||||
ctx.fillStyle = 'white'; |
|
||||||
ctx.textAlign = 'right'; |
|
||||||
for (var i = 0; i <= plot.h; i+=barH/10) { |
|
||||||
ctx.fillText(Math.round(i*vStep)+"", plot.x - gap - barW - gap, barY+barH-i+3); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function drawAxis() { |
|
||||||
var gap = 8; |
|
||||||
var rX0 = plot.x+plot.w; |
|
||||||
var rX = rX0+gap; |
|
||||||
var rY = plot.y; |
|
||||||
var rH = plot.h; |
|
||||||
var rW = 70; |
|
||||||
ctx.clearRect(rX0+.5, rY-10, rW, rH+20); |
|
||||||
|
|
||||||
var perBin = (opts.freq/2) / (opts.sampCount/2); |
|
||||||
|
|
||||||
var totalBins = (plot.h / plot.dy); |
|
||||||
var totalHz = totalBins*perBin; |
|
||||||
|
|
||||||
//console.log("perbin=",perBin,"totalBins=",totalBins,"totalHz=",totalHz);
|
|
||||||
|
|
||||||
var step; |
|
||||||
|
|
||||||
// get the best step size
|
|
||||||
var steps = [10, 25, 50]; |
|
||||||
var multiplier = 1; |
|
||||||
var suc = false; |
|
||||||
do { |
|
||||||
for (var i = 0; i < steps.length; i++) { |
|
||||||
if ((totalHz / (steps[i] * multiplier)) <= 21) { |
|
||||||
step = (steps[i] * multiplier); |
|
||||||
suc = true; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
if (suc) break; |
|
||||||
multiplier *= 10; |
|
||||||
} while (true); |
|
||||||
|
|
||||||
step = step/perBin; |
|
||||||
|
|
||||||
// every step-th bin has a label
|
|
||||||
ctx.font = '12px sans-serif'; |
|
||||||
ctx.fillStyle = 'white'; |
|
||||||
ctx.strokeStyle = 'white'; |
|
||||||
ctx.textAlign = 'left'; |
|
||||||
|
|
||||||
// labels and dashes
|
|
||||||
for(var i = 0; i <= totalBins+step; i+= step) { |
|
||||||
if (i >= totalBins) { |
|
||||||
var dist = i - totalBins; |
|
||||||
if (dist > step/2) break;// make sure not too close
|
|
||||||
i = totalBins; |
|
||||||
} |
|
||||||
|
|
||||||
var hz = i*(totalHz/totalBins); |
|
||||||
if (hz>=1000000) hz = numfmt(hz/1e6,2)+'M'; |
|
||||||
else if (hz>=1000) hz = numfmt(hz/1e3,2)+'k'; |
|
||||||
else hz = numfmt(hz,1); |
|
||||||
|
|
||||||
var yy = Math.round(rY+rH-(plot.dy*i)); |
|
||||||
ctx.fillText(hz, rX, yy+4); |
|
||||||
|
|
||||||
ctx.beginPath(); |
|
||||||
ctx.moveTo(rX0, yy+.5); |
|
||||||
ctx.lineTo(rX0+gap/2, yy+.5); |
|
||||||
ctx.stroke(); |
|
||||||
|
|
||||||
if (i >= totalBins) break; |
|
||||||
} |
|
||||||
|
|
||||||
// Hz label
|
|
||||||
ctx.font = '16px sans-serif'; |
|
||||||
ctx.save(); |
|
||||||
ctx.translate(rX0+50, plot.y+plot.h/2); |
|
||||||
ctx.rotate(Math.PI/2); |
|
||||||
ctx.textAlign = "center"; |
|
||||||
ctx.fillText("Frequency - [Hz]", 0, 0); |
|
||||||
ctx.restore(); |
|
||||||
} |
|
||||||
|
|
||||||
function readOpts() { |
|
||||||
opts.interval = +$('#interval').val(); // ms
|
|
||||||
opts.freq = +$('#freq').val()*2; |
|
||||||
opts.sampCount = +$('#count').val(); |
|
||||||
|
|
||||||
plot.dx = +$('#tile-x').val(); |
|
||||||
plot.dy = +$('#tile-y').val(); |
|
||||||
} |
|
||||||
|
|
||||||
function clearSgArea() { |
|
||||||
ctx.fillStyle = '#000'; |
|
||||||
ctx.fillRect(plot.x, plot.y, plot.w, plot.h); |
|
||||||
ctx.strokeStyle = 'white'; |
|
||||||
ctx.strokeRect(plot.x-.5, plot.y-.5, plot.w+1, plot.h+1); |
|
||||||
} |
|
||||||
|
|
||||||
sg.init = function () { |
|
||||||
var canvas = $('#sg')[0]; |
|
||||||
ctx = canvas.getContext('2d'); |
|
||||||
|
|
||||||
// CLS
|
|
||||||
clearSgArea(); |
|
||||||
readOpts(); |
|
||||||
drawLegend(); |
|
||||||
drawAxis(); |
|
||||||
lastMarkMs = msNow()-10000; |
|
||||||
lastMark10s = msNow()-10000; |
|
||||||
|
|
||||||
// update tile size on bin count selection
|
|
||||||
$('#count').on('change', function() { |
|
||||||
var count = +$('#count').val(); |
|
||||||
var tile = Math.max(1, plot.h/(count/2)); |
|
||||||
|
|
||||||
$('#tile-x').val(Math.max(4, tile)); // use width 4 for smaller by default (rolls more nicely)
|
|
||||||
$('#tile-y').val(tile); |
|
||||||
}); |
|
||||||
|
|
||||||
// chain Y with X
|
|
||||||
$('#tile-y').on('change', function() { |
|
||||||
$('#tile-x').val(Math.max(4,$(this).val())); |
|
||||||
}); |
|
||||||
|
|
||||||
$('#go-btn').on('click', function() { |
|
||||||
running = !running; |
|
||||||
if (running) { |
|
||||||
readOpts(); |
|
||||||
drawAxis(); |
|
||||||
|
|
||||||
requestData(); |
|
||||||
} else { |
|
||||||
clearTimeout(readTimeout); |
|
||||||
} |
|
||||||
|
|
||||||
$('#go-btn') |
|
||||||
.toggleClass('btn-green') |
|
||||||
.toggleClass('btn-red') |
|
||||||
.html(running ? 'Stop' : 'Start'); |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
return sg; |
|
||||||
})(); |
|
@ -1,88 +0,0 @@ |
|||||||
var page_status = (function() { |
|
||||||
var st = {}; |
|
||||||
st.j = {}; |
|
||||||
|
|
||||||
var updateTime = 10000; |
|
||||||
|
|
||||||
var updateInhibited = false; |
|
||||||
|
|
||||||
st.trigReset = function() { |
|
||||||
var modal_sel = '#reset-modal'; |
|
||||||
$().get(_root + '/system/reset', function(resp, status) { |
|
||||||
if (status == 200) { |
|
||||||
|
|
||||||
modal.show(modal_sel); |
|
||||||
updateInhibited = true; |
|
||||||
|
|
||||||
var ping_i = setInterval(function() { |
|
||||||
$().get(_root+'/system/ping', function(resp, code){ |
|
||||||
if (code == 200) { |
|
||||||
// device is ready
|
|
||||||
modal.hide(modal_sel); |
|
||||||
requestUpdate(); |
|
||||||
clearInterval(ping_i); |
|
||||||
updateInhibited = false; |
|
||||||
} |
|
||||||
}, {timeout: 500}); |
|
||||||
}, 1000); |
|
||||||
} |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
function onUpdate(resp, status) { |
|
||||||
if (status != 200) { |
|
||||||
// bad response
|
|
||||||
errorMsg('Update failed.'); |
|
||||||
} else { |
|
||||||
try { |
|
||||||
// OK
|
|
||||||
var j = JSON.parse(resp); |
|
||||||
st.j = j; // store for global access
|
|
||||||
|
|
||||||
$('.sta-only').toggle(j.sta); |
|
||||||
$('.ap-only').toggle(j.ap); |
|
||||||
|
|
||||||
$('#uptime').html(j.uptime); |
|
||||||
$('#heap').html(j.heap + " bytes"); |
|
||||||
$('#wmode').html(j.wifiMode); |
|
||||||
|
|
||||||
if (j.sta) { |
|
||||||
$('#staSSID').html(j.sta.SSID); |
|
||||||
$('#staRSSIperc').html(j.sta.RSSIperc); |
|
||||||
$('#staRSSI').html(j.sta.RSSI); |
|
||||||
$('#staMAC').html(j.sta.MAC); |
|
||||||
} |
|
||||||
|
|
||||||
if (j.ap) { |
|
||||||
$('#apSSID').html(j.ap.SSID); |
|
||||||
$('#apHidden').html(j.ap.hidden ? "Yes" : "No"); |
|
||||||
$('#apAuth').html(j.ap.auth); |
|
||||||
|
|
||||||
// hide the password row if auth is Open
|
|
||||||
$('.ap-auth-only').toggle(j.ap.auth != 'Open'); |
|
||||||
|
|
||||||
$('#apPwd').html(j.ap.pwd); |
|
||||||
$('#apChan').html(j.ap.chan); |
|
||||||
$('#apMAC').html(j.ap.MAC); |
|
||||||
} |
|
||||||
// chip ID & macs don't change
|
|
||||||
} catch(e) { |
|
||||||
errorMsg(e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (!updateInhibited) { |
|
||||||
setTimeout(requestUpdate, updateTime); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function requestUpdate() { |
|
||||||
$().get(_root+'/system/status', onUpdate); |
|
||||||
} |
|
||||||
|
|
||||||
st.init = function() { |
|
||||||
requestUpdate(); |
|
||||||
}; |
|
||||||
|
|
||||||
return st; |
|
||||||
})(); |
|
@ -1,271 +0,0 @@ |
|||||||
var page_waveform = (function () { |
|
||||||
var wfm = {}; |
|
||||||
|
|
||||||
var zoomResetFn; |
|
||||||
var dataFormat; |
|
||||||
|
|
||||||
var readoutPending = false; |
|
||||||
var autoReload = false; |
|
||||||
var autoReloadTime = 1; |
|
||||||
var arTimeout = -1; |
|
||||||
|
|
||||||
var lastLoadMs; |
|
||||||
|
|
||||||
var zoomSavedX, zoomSavedY; |
|
||||||
|
|
||||||
var readXhr; // read xhr
|
|
||||||
|
|
||||||
var lastObj = null; // samples are stored here
|
|
||||||
|
|
||||||
var opts = { |
|
||||||
count: 0, // sample count
|
|
||||||
freq: 0 // sampling freq
|
|
||||||
}; |
|
||||||
|
|
||||||
function buildChart(j) { |
|
||||||
// Build the chart
|
|
||||||
var mql = window.matchMedia('screen and (min-width: 544px)'); |
|
||||||
var isPhone = !mql.matches; |
|
||||||
|
|
||||||
var fft = (j.stats.format == 'FFT'); |
|
||||||
|
|
||||||
var xLabel, yLabel; |
|
||||||
if (fft) { |
|
||||||
xLabel = 'Frequency - [ Hz ]'; |
|
||||||
yLabel = 'Magnitude - [ mA ]'; |
|
||||||
} else { |
|
||||||
xLabel = 'Sample time - [ ms ]'; |
|
||||||
yLabel = 'Current - [ mA ]'; |
|
||||||
} |
|
||||||
|
|
||||||
var peak = Math.max(-j.stats.min, j.stats.max); |
|
||||||
var displayPeak = Math.max(peak, 10); |
|
||||||
|
|
||||||
// Sidebar
|
|
||||||
|
|
||||||
$('#stat-count').html(j.stats.count); |
|
||||||
$('#stat-f-s').html(numfmt(j.stats.freq, 2)); |
|
||||||
$('#stat-i-peak').html(numfmt(peak, 2)); |
|
||||||
$('#stat-i-rms').html(numfmt(j.stats.rms, 2)); |
|
||||||
$('.stats').removeClass('invis'); |
|
||||||
|
|
||||||
// --- chart ---
|
|
||||||
|
|
||||||
// Generate point entries
|
|
||||||
// add synthetic properties
|
|
||||||
var step = fft ? (j.stats.freq/j.stats.count) : (1000/j.stats.freq); |
|
||||||
var points = _.map(j.samples, function (a, i) { |
|
||||||
return { |
|
||||||
x: i * step, |
|
||||||
y: a |
|
||||||
}; |
|
||||||
}); |
|
||||||
|
|
||||||
var plugins = [ |
|
||||||
Chartist.plugins.zoom({ |
|
||||||
resetOnRightMouseBtn: true, |
|
||||||
onZoom: function (chart, reset) { |
|
||||||
zoomResetFn = reset; |
|
||||||
|
|
||||||
zoomSavedX = chart.options.axisX.highLow; |
|
||||||
zoomSavedY = chart.options.axisY.highLow; |
|
||||||
} |
|
||||||
}) |
|
||||||
]; |
|
||||||
|
|
||||||
if (!isPhone) plugins.push( // larger than phone
|
|
||||||
Chartist.plugins.ctAxisTitle({ |
|
||||||
axisX: { |
|
||||||
axisTitle: xLabel, |
|
||||||
offset: { |
|
||||||
x: 0, |
|
||||||
y: 55 |
|
||||||
} |
|
||||||
}, |
|
||||||
axisY: { |
|
||||||
axisTitle: yLabel, |
|
||||||
flipText: true, |
|
||||||
offset: { |
|
||||||
x: 0, |
|
||||||
y: 15 |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
); |
|
||||||
|
|
||||||
var xHigh, xLow, yHigh, yLow; |
|
||||||
|
|
||||||
if (zoomSavedX) { |
|
||||||
// we have saved coords of the zoom rect, restore the zoom.
|
|
||||||
xHigh = zoomSavedX.high; |
|
||||||
xLow = zoomSavedX.low; |
|
||||||
yHigh = zoomSavedY.high; |
|
||||||
yLow = zoomSavedY.low; |
|
||||||
} else { |
|
||||||
yHigh = fft ? undefined : displayPeak; |
|
||||||
yLow = fft ? 0 : -displayPeak; |
|
||||||
} |
|
||||||
|
|
||||||
new Chartist.Line('#chart', { |
|
||||||
series: [ |
|
||||||
{ |
|
||||||
name: 'a', |
|
||||||
data: points |
|
||||||
}, |
|
||||||
] |
|
||||||
}, { |
|
||||||
showPoint: false, |
|
||||||
showArea: fft, |
|
||||||
fullWidth: true, |
|
||||||
chartPadding: (isPhone ? {right: 20, bottom: 5, left: 0} : {right: 25, bottom: 30, left: 25}), |
|
||||||
series: { |
|
||||||
'a': { |
|
||||||
lineSmooth: Chartist.Interpolation.monotoneCubic() |
|
||||||
} |
|
||||||
}, |
|
||||||
axisX: { |
|
||||||
type: Chartist.AutoScaleAxis, |
|
||||||
//onlyInteger: !fft // only for raw
|
|
||||||
high: xHigh, |
|
||||||
low: xLow, |
|
||||||
}, |
|
||||||
axisY: { |
|
||||||
type: Chartist.AutoScaleAxis, |
|
||||||
//onlyInteger: true
|
|
||||||
high: yHigh, |
|
||||||
low: yLow, |
|
||||||
}, |
|
||||||
explicitBounds: { |
|
||||||
xLow: 0, |
|
||||||
yLow: fft ? 0 : undefined, |
|
||||||
xHigh: points[points.length-1].x |
|
||||||
}, |
|
||||||
plugins: plugins |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
function onRxData(resp, status) { |
|
||||||
readoutPending = false; |
|
||||||
|
|
||||||
if (status != 200) { |
|
||||||
errorMsg("Request failed.", 1000); |
|
||||||
} else { |
|
||||||
var j = JSON.parse(resp); |
|
||||||
if (!j.success) { |
|
||||||
errorMsg("Sampling failed.", 1000); |
|
||||||
} else { |
|
||||||
$('.chartexport').removeClass('hidden'); |
|
||||||
lastObj = j; |
|
||||||
buildChart(j); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (autoReload) |
|
||||||
arTimeout = setTimeout(requestReload, Math.max(0, autoReloadTime - msElapsed(lastLoadMs))); |
|
||||||
} |
|
||||||
|
|
||||||
function readInputs() { |
|
||||||
opts.count = $('#count').val(); |
|
||||||
opts.freq = $('#freq').val() * (dataFormat == 'fft' ? 2 : 1); // bw 2x -> f_s
|
|
||||||
} |
|
||||||
|
|
||||||
function requestReload() { |
|
||||||
if (readoutPending) { |
|
||||||
errorMsg("Request already pending - aborting."); |
|
||||||
readXhr.abort(); |
|
||||||
} |
|
||||||
|
|
||||||
readoutPending = true; |
|
||||||
lastLoadMs = msNow(); |
|
||||||
|
|
||||||
var n = opts.count; |
|
||||||
var fs = opts.freq; |
|
||||||
var url = _root+'/measure/'+dataFormat+'?n='+n+'&fs='+fs; |
|
||||||
readXhr = $().get(url, onRxData, estimateLoadTime(fs,n)); |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
function toggleAutoReload() { |
|
||||||
autoReloadTime = +$('#ar-time').val(); // ms
|
|
||||||
|
|
||||||
readInputs(); |
|
||||||
|
|
||||||
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; |
|
||||||
|
|
||||||
function onLoadClick() { |
|
||||||
readInputs(); |
|
||||||
requestReload(); |
|
||||||
} |
|
||||||
|
|
||||||
$('#load').on('click', onLoadClick); |
|
||||||
|
|
||||||
$('.chartexport a').on('click', function() { |
|
||||||
var sep = $(this).data('sep'); |
|
||||||
var str = ''; |
|
||||||
|
|
||||||
var isFft = (dataFormat == 'fft'); |
|
||||||
var csvStep = isFft ? (lastObj.stats.freq/lastObj.stats.count) : (1000/lastObj.stats.freq); |
|
||||||
var csvPlaces = isFft ? 3 : 2; |
|
||||||
|
|
||||||
switch (sep) { |
|
||||||
case 'space': str = lastObj.samples.join(' '); break; |
|
||||||
case 'comma': str = lastObj.samples.join(','); break; |
|
||||||
case 'newline': str = lastObj.samples.join('\n'); break; |
|
||||||
|
|
||||||
case 'csv': |
|
||||||
str = _.map(lastObj.samples, function (a, i) { |
|
||||||
return numfmt(i * csvStep, csvPlaces) + "," + a; |
|
||||||
}).join('\n'); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
if (!copyToClipboard(str)) { |
|
||||||
var $cb = $('#copybox'); |
|
||||||
$cb.removeClass('hidden'); |
|
||||||
$cb.val(str); |
|
||||||
} else { |
|
||||||
infoMsg('Copy success!'); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
$('#count,#freq').on('keyup', function (e) { |
|
||||||
if (e.which == 13) { |
|
||||||
onLoadClick(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
// --- zooming ---
|
|
||||||
|
|
||||||
$('#chart').on('contextmenu', function (e) { // right click on the chart -> reset
|
|
||||||
zoomResetFn && zoomResetFn(); |
|
||||||
zoomResetFn = null; |
|
||||||
|
|
||||||
zoomSavedX = null; |
|
||||||
zoomSavedY = null; |
|
||||||
|
|
||||||
e.preventDefault(); |
|
||||||
return false; |
|
||||||
}); |
|
||||||
|
|
||||||
// auto-reload button
|
|
||||||
$('#ar-btn').on('click', toggleAutoReload); |
|
||||||
}; |
|
||||||
|
|
||||||
return wfm; |
|
||||||
})(); |
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@ |
|||||||
0648559aed5a9ec1d478b445839bdb807ced7fc5 |
|
@ -1,48 +0,0 @@ |
|||||||
<?php $page = 'about'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>About</h1> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<img src="/img/cvut.svg" id="logo" class="mq-tablet-min"> |
|
||||||
<h2><?= e($appname) ?></h2>
|
|
||||||
|
|
||||||
<img src="/img/cvut.svg" id="logo2" class="mq-phone"> |
|
||||||
|
|
||||||
<p>© Ondřej Hruška, 2016 <<a href="mailto:ondra@ondrovo.com" target="blank">ondra@ondrovo.com</a>></p> |
|
||||||
|
|
||||||
<p><a href="http://measure.feld.cvut.cz/" target="blank">Katedra měření, FEL ČVUT</a><br>Department of Measurement, FEE CTU</p> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Firmware</h2> |
|
||||||
|
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Firmware</th> |
|
||||||
<td>v%vers_fw%, build <i>%date%</i> at <i>%time%</i></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>esp-httpd lib</th> |
|
||||||
<td>v%vers_httpd%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>SBMP lib</th> |
|
||||||
<td>v%vers_sbmp%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>ESP IoT SDK</th> |
|
||||||
<td>v%vers_sdk%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>STM32 firmware</th> |
|
||||||
<td>v%vers_stm%</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
|
|
||||||
<p> |
|
||||||
The webserver was built using the great <a href="https://github.com/Spritetm/esphttpd" target="blank">esp-httpd</a> |
|
||||||
library by Jeroen Domburg. |
|
||||||
</p> |
|
||||||
</div> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -1,73 +0,0 @@ |
|||||||
<?php $page = 'fft'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>FFT</h1> |
|
||||||
|
|
||||||
<div class="Box center" id="samp-ctrl"> |
|
||||||
<div> |
|
||||||
<label for="count">Bins</label> |
|
||||||
<label for="count" class="select-wrap"> |
|
||||||
<select name="count" id="count"> |
|
||||||
<option value="16">8 |
|
||||||
<option value="32">16 |
|
||||||
<option value="64">32 |
|
||||||
<option value="128">64 |
|
||||||
<option value="256">128 |
|
||||||
<option value="512">256 |
|
||||||
<option value="1024">512 |
|
||||||
<option value="2048" selected>1024 |
|
||||||
</select> |
|
||||||
</label> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="freq">f<sub>bw</sub> <span class="mq-normal-min nb">=</span><span class="mq-tablet-max nb">(Hz)</span></label> |
|
||||||
<input id="freq" type="number" value="2048"> |
|
||||||
<span class="mq-normal-min">Hz</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<a id="load" class="button btn-green">Load</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box medium chartbox"> |
|
||||||
<div id="chart" class="ct-chart ct-wide ct-with-area"></div> |
|
||||||
<div class="stats invis"> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Samples</th> |
|
||||||
<td id="stat-count"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>f<sub>s</sub></th> |
|
||||||
<td id="stat-f-s"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>peak</sub></th> |
|
||||||
<td id="stat-i-peak"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>RMS</sub></th> |
|
||||||
<td id="stat-i-rms"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
<div class="ar"><!-- auto reload --> |
|
||||||
<input type="number" id="ar-time" step="100" value="1000" min="0"> ms |
|
||||||
<input type="button" id="ar-btn" class="btn-blue narrow" value="Auto"> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box chartexport hidden"> |
|
||||||
Copy: |
|
||||||
<a data-sep="space">1·2·3</a> |
|
||||||
<a data-sep="comma">1,2,3</a> |
|
||||||
<a data-sep="newline">1↵2↵3</a> |
|
||||||
<a data-sep="csv">CSV</a> |
|
||||||
<br> |
|
||||||
<textarea id="copybox" class="hidden" readonly onfocus="this.select();" onmouseup="return false"></textarea> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_waveform.init('fft')); |
|
||||||
</script> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -0,0 +1,21 @@ |
|||||||
|
<?php $page = 'home'; |
||||||
|
include "_start.php"; ?> |
||||||
|
|
||||||
|
<h1>Home</h1> |
||||||
|
|
||||||
|
<div class="Box"> |
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus cum eius molestias nesciunt nihil sequi? Laboriosam molestiae nesciunt |
||||||
|
quis! Aut eius esse in laudantium obcaecati possimus quis repudiandae tenetur velit.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="Box"> |
||||||
|
<h2>Firmware</h2> |
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus cum eius molestias nesciunt nihil sequi? Laboriosam molestiae nesciunt |
||||||
|
quis! Aut eius esse in laudantium obcaecati possimus quis repudiandae tenetur velit.</p> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script> |
||||||
|
$().ready(page_home.init); |
||||||
|
</script> |
||||||
|
|
||||||
|
<?php include "_end.php"; ?> |
@ -1,73 +0,0 @@ |
|||||||
<?php $page = 'monitoring'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>Monitoring & Reporting</h1> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Status</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Reference:</th> |
|
||||||
<td> |
|
||||||
<span id="hasref" class="Valfield">%refStored%</span> |
|
||||||
<a onclick="page_mon.captureRef()" class="button btn-green">Capture</a> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Status:</th> |
|
||||||
<td> |
|
||||||
<span class="Valfield" style="vertical-align:middle;"> |
|
||||||
Δ = <span id="actual-dev">%curDeviation%</span><br> |
|
||||||
I<sub>RMS</sub> = <span id="actual-rms">%curRMS%</span> mA |
|
||||||
</span> |
|
||||||
<a onclick="page_mon.compareNow()" class="button btn-blue">Measure</a> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Reporting</h2> |
|
||||||
<form action="<?=$root?>/mon/config" method="POST">
|
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th><label for="rep-on">Reporting:</label></th> |
|
||||||
<td> |
|
||||||
<input type="checkbox" id="rep-on" name="enabled" value="1" %rep_en%><!-- |
|
||||||
--> <label for="rep-on">enabled</label> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th><label for="rep-interval">Interval:</label></th> |
|
||||||
<td> |
|
||||||
<input type="number" name="interval" id="rep-interval" style="max-width: 10em" value="%repInterval%"><!-- |
|
||||||
--> seconds |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Service:</th> |
|
||||||
<td> |
|
||||||
<input type="radio" name="service" value="xv" id="rep-svc-xv" %svc_xv%> <label for="rep-svc-xv">Xively</label> |
|
||||||
<input type="radio" name="service" value="ts" id="rep-svc-ts" %svc_ts%> <label for="rep-svc-ts">ThingSpeak</label> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th><label for="rep-key">API key:</label></th> |
|
||||||
<td><input type="text" name="key" id="rep-key" value="%repKey%"></td> |
|
||||||
</tr> |
|
||||||
<tr class="xv-only"> |
|
||||||
<th><label for="rep-feed">Feed ID:</label></th> |
|
||||||
<td><input type="text" name="feed" id="rep-feed" value="%repFeed%"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th> </th> |
|
||||||
<td><input type="submit" value="Save changes"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_mon.init); |
|
||||||
</script> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -1,50 +0,0 @@ |
|||||||
<?php $page = 'spectrogram'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>Spectrogram</h1> |
|
||||||
|
|
||||||
<div class="Box center" id="samp-ctrl"> |
|
||||||
<div> |
|
||||||
<label for="count">Bins</label> |
|
||||||
<label for="count" class="select-wrap"> |
|
||||||
<select name="count" id="count"> |
|
||||||
<option value="16">8 |
|
||||||
<option value="32">16 |
|
||||||
<option value="64">32 |
|
||||||
<option value="128">64 |
|
||||||
<option value="256">128 |
|
||||||
<option value="512">256 |
|
||||||
<option value="1024" selected>512 |
|
||||||
<option value="2048">1024 |
|
||||||
</select> |
|
||||||
</label> |
|
||||||
</div> |
|
||||||
<div id="tile-cfg"> |
|
||||||
<label for="tile-x">Tile</label> |
|
||||||
<input id="tile-x" type="number" min=1 step=1 value=4> |
|
||||||
× |
|
||||||
<input id="tile-y" type="number" min=1 step=1 value=1> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="freq">f<sub>bw</sub> <span class="mq-normal-min nb">=</span><span class="mq-tablet-max nb">(Hz)</span></label> |
|
||||||
<input id="freq" type="number" value="2048"> |
|
||||||
<span class="mq-normal-min">Hz</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="interval">Interval <span class="mq-tablet-max" style="font-weight:normal;">(ms)</span></label> |
|
||||||
<input id="interval" type="number" value="0" step=100 min=0> |
|
||||||
<span class="mq-normal-min">ms</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<a id="go-btn" class="button btn-green">Start</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box center"> |
|
||||||
<canvas id="sg" width=860 height=530></canvas> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_spectrogram.init()); |
|
||||||
</script> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -1,99 +0,0 @@ |
|||||||
<?php $page = 'home'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>System Status</h1> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>Runtime</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Uptime:</th> |
|
||||||
<td id="uptime">%uptime%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Free heap:</th> |
|
||||||
<td id="heap">%heap%</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th></th> |
|
||||||
<td><a onclick="page_status.trigReset()" class="button btn-red">Restart system</a></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<h2>WiFi</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>WiFi mode:</th> |
|
||||||
<td id="wmode">%wifiMode%</td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<!-- WiFi info is read & updated using AJAX --> |
|
||||||
|
|
||||||
<div class="Box sta-only" style="display:none"> |
|
||||||
<h2>WiFi Station</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>SSID:</th> |
|
||||||
<td id="staSSID"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>RSSI:</th> |
|
||||||
<td> |
|
||||||
<span id="staRSSIperc"></span>, |
|
||||||
<span id="staRSSI"></span> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>MAC:</th> |
|
||||||
<td id="staMAC"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box ap-only" style="display:none"> |
|
||||||
<h2>WiFi AP</h2> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>SSID:</th> |
|
||||||
<td id="apSSID"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Hidden:</th> |
|
||||||
<td id="apHidden"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Auth. mode:</th> |
|
||||||
<td id="apAuth"></td> |
|
||||||
</tr> |
|
||||||
<tr class="ap-auth-only"> |
|
||||||
<th>Password:</th> |
|
||||||
<td id="apPwd"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>Channel:</th> |
|
||||||
<td id="apChan"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>MAC:</th> |
|
||||||
<td id="apMAC"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Modal hidden no-close" id="reset-modal"> |
|
||||||
<div class="Dialog center"> |
|
||||||
<h2>The device has been reset.</h2> |
|
||||||
<p class="ap-only">If you're connected to the AP, you'll have to re-connect.</p> |
|
||||||
<p>This dialog should close when the restart is complete, please wait around 15 seconds..</p> |
|
||||||
<p><a onclick="location.reload()" class="button btn-blue">Reload the page</a></p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_status.init); |
|
||||||
</script> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -1,62 +0,0 @@ |
|||||||
<?php $page = 'waveform'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>Waveform</h1> |
|
||||||
|
|
||||||
<div class="Box center" id="samp-ctrl"> |
|
||||||
<div> |
|
||||||
<label for="count">Samples</label> |
|
||||||
<input id="count" type="number" value="500"> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<label for="freq">f<sub>s</sub> <span class="mq-normal-min nb">=</span><span class="mq-tablet-max nb">(Hz)</span></label> |
|
||||||
<input id="freq" type="number" value="2048"> |
|
||||||
<span class="mq-normal-min">Hz</span> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<a id="load" class="button btn-green">Load</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box medium chartbox"> |
|
||||||
<div id="chart" class="ct-chart ct-wide"></div> |
|
||||||
<div class="stats invis"> |
|
||||||
<table> |
|
||||||
<tr> |
|
||||||
<th>Samples</th> |
|
||||||
<td id="stat-count"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>f<sub>s</sub></th> |
|
||||||
<td id="stat-f-s"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>peak</sub></th> |
|
||||||
<td id="stat-i-peak"></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>I<sub>RMS</sub></th> |
|
||||||
<td id="stat-i-rms"></td> |
|
||||||
</tr> |
|
||||||
</table> |
|
||||||
<div class="ar"><!-- auto reload --> |
|
||||||
<input type="number" id="ar-time" step="100" value="1000" min="0"> ms |
|
||||||
<input type="button" id="ar-btn" class="btn-blue narrow" value="Auto"> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="Box chartexport hidden"> |
|
||||||
Copy: |
|
||||||
<a data-sep="space">1·2·3</a> |
|
||||||
<a data-sep="comma">1,2,3</a> |
|
||||||
<a data-sep="newline">1↵2↵3</a> |
|
||||||
<a data-sep="csv">CSV</a> |
|
||||||
<br> |
|
||||||
<textarea id="copybox" class="hidden" readonly onfocus="this.select();" onmouseup="return false"></textarea> |
|
||||||
</div> |
|
||||||
|
|
||||||
<script> |
|
||||||
$().ready(page_waveform.init('raw')); |
|
||||||
</script> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -1,17 +0,0 @@ |
|||||||
.page-about { |
|
||||||
.Box { |
|
||||||
padding-left:dist(0); |
|
||||||
padding-right:dist(0); |
|
||||||
|
|
||||||
a {font-weight: bold;} |
|
||||||
} |
|
||||||
|
|
||||||
#logo { |
|
||||||
float:right; |
|
||||||
height: 130px; |
|
||||||
} |
|
||||||
|
|
||||||
#logo2 { |
|
||||||
max-width: 150px; |
|
||||||
} |
|
||||||
} |
|
@ -1,11 +1,17 @@ |
|||||||
.page-home #staRSSIperc:after { |
.page-about { |
||||||
padding-left: dist(-4); |
.Box { |
||||||
content: '%'; |
padding-left:dist(0); |
||||||
font-size: fsize(-1); |
padding-right:dist(0); |
||||||
} |
|
||||||
|
a {font-weight: bold;} |
||||||
|
} |
||||||
|
|
||||||
|
#logo { |
||||||
|
float:right; |
||||||
|
height: 130px; |
||||||
|
} |
||||||
|
|
||||||
.page-home #staRSSI:after { |
#logo2 { |
||||||
padding-left: dist(-4); |
max-width: 150px; |
||||||
content: 'dBm'; |
} |
||||||
font-size: fsize(-1); |
|
||||||
} |
} |
||||||
|
@ -1,101 +0,0 @@ |
|||||||
#samp-ctrl { |
|
||||||
display: flex; |
|
||||||
padding: dist(-2); |
|
||||||
|
|
||||||
flex-direction: row; |
|
||||||
@include media($phone) { |
|
||||||
flex-direction: column; |
|
||||||
} |
|
||||||
|
|
||||||
justify-content: center; |
|
||||||
align-items: stretch; |
|
||||||
|
|
||||||
> div { |
|
||||||
margin: dist(-2) dist(-1); |
|
||||||
} |
|
||||||
|
|
||||||
label { |
|
||||||
line-height: 1.8; |
|
||||||
font-weight: bold; |
|
||||||
} |
|
||||||
|
|
||||||
input,select { |
|
||||||
width: 6em; |
|
||||||
|
|
||||||
@include media($phone) { |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// -- spectrogram -- |
|
||||||
|
|
||||||
#tile-cfg input { |
|
||||||
width: 3em; |
|
||||||
} |
|
||||||
|
|
||||||
#interval { |
|
||||||
width: 4.5em; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
.Box.chartbox { |
|
||||||
display: flex; |
|
||||||
flex-direction: row; |
|
||||||
|
|
||||||
@include media($phone) { |
|
||||||
flex-direction: column; |
|
||||||
} |
|
||||||
|
|
||||||
.stats { |
|
||||||
flex: 0 1; |
|
||||||
position: relative; |
|
||||||
|
|
||||||
@include media($phone) { |
|
||||||
table { |
|
||||||
margin: 0 auto; |
|
||||||
} // center the table |
|
||||||
|
|
||||||
td,th { |
|
||||||
width: 50%; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
th,td { |
|
||||||
@include nowrap; |
|
||||||
} |
|
||||||
|
|
||||||
th sub { font-weight: normal;} |
|
||||||
|
|
||||||
td { |
|
||||||
min-width: 100px; |
|
||||||
} |
|
||||||
|
|
||||||
td:after { |
|
||||||
font-size: 90%; |
|
||||||
padding-left: .5em; |
|
||||||
} |
|
||||||
|
|
||||||
//#stat-count |
|
||||||
#stat-f-s:after {content: "Hz"} |
|
||||||
#stat-i-peak:after {content: "mA"} |
|
||||||
#stat-i-rms:after {content: "mA"} |
|
||||||
|
|
||||||
padding-bottom: 50px; |
|
||||||
|
|
||||||
// auto reload box |
|
||||||
.ar { |
|
||||||
position: absolute; |
|
||||||
bottom:dist(-2); |
|
||||||
width:100%; |
|
||||||
text-align: center; |
|
||||||
|
|
||||||
input[type=number] { |
|
||||||
width: 4em; |
|
||||||
} |
|
||||||
|
|
||||||
input[type=button] { |
|
||||||
margin-left: dist(-2); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,71 +0,0 @@ |
|||||||
<?php $page='home'; include "_start.php"; ?> |
|
||||||
|
|
||||||
<h1>Heading sdfsd sdfsd</h1> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium et fugit, labore molestiae provident veniam. Architecto deserunt eos esse fuga, hic inventore maxime minima natus non quas quibusdam sunt suscipit.</div> |
|
||||||
|
|
||||||
<div class="Box wide"><b>This is a wide box for like a graph or whatever.</b><br> |
|
||||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid asperiores consectetur debitis deleniti dicta dignissimos dolores eveniet exercitationem ipsa iste necessitatibus nemo, odit pariatur provident repellat ullam ut veniam vero!</div> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur aut commodi culpa et fugit laboriosam, minus praesentium recusandae ullam voluptates. Alias culpa, cupiditate ducimus est id ipsum optio quam voluptate!</div> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur ex rerum tempore voluptates? Accusamus corporis, dolorem enim <a href="#">This is a link</a>. ipsum molestiae molestias non odit perspiciatis repellendus sint, soluta, tempore tenetur vitae voluptate!</div> |
|
||||||
|
|
||||||
|
|
||||||
<div class="Box"> |
|
||||||
<form action="#"> |
|
||||||
<div class="Row"> |
|
||||||
<label for="xoxo">Text</label> |
|
||||||
<input id="xoxo" name="xoxo" type="text" value="I'm a text input"> |
|
||||||
</div> |
|
||||||
<div class="Row checkbox"> |
|
||||||
<div class="checkbox-wrap"><input id="aa" name="aa" type="checkbox" value=asdf"></div> |
|
||||||
<label for="aa">Checkbox</label> |
|
||||||
</div> |
|
||||||
<div class="Row"> |
|
||||||
<label for="sss">Number</label> |
|
||||||
<input id="sss" name="sss" type="number" value="123"> |
|
||||||
</div> |
|
||||||
<div class="Row"> |
|
||||||
<label for="sss">Password</label> |
|
||||||
<input id="sss" name="sss" type="password" value="123"> |
|
||||||
</div> |
|
||||||
<div class="Row"> |
|
||||||
<label for="sss">Yo textarea</label> |
|
||||||
<textarea>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias aperiam assumenda blanditiis, commodi cumque debitis harum in inventore ipsum iusto laudantium minima molestias nam nemo nihil nulla perferendis, porro vel?</textarea> |
|
||||||
</div> |
|
||||||
<div class="Row buttons"> |
|
||||||
<div class="spacer"></div> |
|
||||||
<input type="submit" value="Send"> |
|
||||||
<input type="reset" value="Clear"> |
|
||||||
</div> |
|
||||||
<div class="Row checkbox"> |
|
||||||
<div class="checkbox-wrap"><input id="aa" name="aa" type="checkbox" value=asdf"></div> |
|
||||||
<label for="aa">Checkbox</label> |
|
||||||
</div> |
|
||||||
<div class="Row"> |
|
||||||
<label for="sss">Select!!</label> |
|
||||||
<label for="sdsd" class="select-wrap"> |
|
||||||
<select name="sdsd" id="sdsd"> |
|
||||||
<option value="sdfsf">sfsdf</option> |
|
||||||
<option value="fff">fff</option> |
|
||||||
<option value="dddd">dddddd</option> |
|
||||||
</select> |
|
||||||
</label> |
|
||||||
</div> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur aut commodi culpa et fugit laboriosam, minus praesentium recusandae ullam voluptates. Alias culpa, cupiditate ducimus est id ipsum optio quam voluptate!</div> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur aut commodi culpa et fugit laboriosam, minus praesentium recusandae ullam voluptates. Alias culpa, cupiditate ducimus est id ipsum optio quam voluptate!</div> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur aut commodi culpa et fugit laboriosam, minus praesentium recusandae ullam voluptates. Alias culpa, cupiditate ducimus est id ipsum optio quam voluptate!</div> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur aut commodi culpa et fugit laboriosam, minus praesentium recusandae ullam voluptates. Alias culpa, cupiditate ducimus est id ipsum optio quam voluptate!</div> |
|
||||||
|
|
||||||
<div class="Box">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur aut commodi culpa et fugit laboriosam, minus praesentium recusandae ullam voluptates. Alias culpa, cupiditate ducimus est id ipsum optio quam voluptate!</div> |
|
||||||
|
|
||||||
<?php include "_end.php"; ?> |
|
@ -1,83 +0,0 @@ |
|||||||
#include <esp8266.h> |
|
||||||
#include <httpd.h> |
|
||||||
#include "page_about.h" |
|
||||||
#include "fw_version.h" |
|
||||||
#include "sbmp.h" |
|
||||||
#include "datalink.h" |
|
||||||
#include "serial.h" |
|
||||||
|
|
||||||
static bool stm_vers_loaded = false; |
|
||||||
static char stm_vers_buf[10]; |
|
||||||
|
|
||||||
static void readVersionCB(SBMP_Endpoint *ep, SBMP_Datagram *dg, void** arg) |
|
||||||
{ |
|
||||||
(void)ep; |
|
||||||
(void)arg; |
|
||||||
|
|
||||||
if (dg->type != DG_SUCCESS) { |
|
||||||
error("Response to REQUEST_VERSION not SUCCESS."); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
sprintf(stm_vers_buf, "%d.%d.%d", dg->payload[0], dg->payload[1], dg->payload[2]); |
|
||||||
stm_vers_loaded = true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** "About" page */ |
|
||||||
httpd_cgi_state FLASH_FN tplAbout(HttpdConnData *connData, char *token, void **arg) |
|
||||||
{ |
|
||||||
// arg is unused
|
|
||||||
(void)arg; |
|
||||||
|
|
||||||
if (token == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
if (streq(token, "vers_fw")) { |
|
||||||
httpdSend(connData, FIRMWARE_VERSION, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "date")) { |
|
||||||
httpdSend(connData, __DATE__, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "time")) { |
|
||||||
httpdSend(connData, __TIME__, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "vers_httpd")) { |
|
||||||
httpdSend(connData, HTTPDVER, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "vers_sbmp")) { |
|
||||||
httpdSend(connData, SBMP_VER, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "vers_sdk")) { |
|
||||||
httpdSend(connData, STR(ESP_SDK_VERSION), -1); |
|
||||||
|
|
||||||
} else if (streq(token, "vers_stm")) { |
|
||||||
|
|
||||||
if (stm_vers_loaded) { |
|
||||||
httpdSend(connData, stm_vers_buf, -1); |
|
||||||
} else { |
|
||||||
|
|
||||||
uint16_t sesn; |
|
||||||
sbmp_ep_send_message(dlnk_ep, DG_REQUEST_STM_VERSION, NULL, 0, &sesn, NULL); |
|
||||||
sbmp_ep_add_listener(dlnk_ep, sesn, readVersionCB, NULL); |
|
||||||
|
|
||||||
sprintf(stm_vers_buf, "???"); |
|
||||||
|
|
||||||
// poll & wait for response
|
|
||||||
const int timeout = 100; |
|
||||||
for (uint32_t i = 0; i < timeout * 100; i++) { |
|
||||||
uart_poll(); |
|
||||||
|
|
||||||
if (stm_vers_loaded) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
os_delay_us(10); |
|
||||||
system_soft_wdt_feed(); // Feed the dog, or it'll bite.
|
|
||||||
} |
|
||||||
|
|
||||||
httpdSend(connData, stm_vers_buf, -1); // send to view
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
@ -0,0 +1,23 @@ |
|||||||
|
#include <esp8266.h> |
||||||
|
#include <httpd.h> |
||||||
|
#include "fw_version.h" |
||||||
|
#include "sbmp.h" |
||||||
|
#include "datalink.h" |
||||||
|
#include "serial.h" |
||||||
|
|
||||||
|
|
||||||
|
/** "Home" page */ |
||||||
|
httpd_cgi_state FLASH_FN tplHome(HttpdConnData *connData, char *token, void **arg) |
||||||
|
{ |
||||||
|
// arg is unused
|
||||||
|
(void)arg; |
||||||
|
(void)connData; |
||||||
|
|
||||||
|
if (token == NULL) return HTTPD_CGI_DONE; |
||||||
|
|
||||||
|
// if (streq(token, "vers_fw")) {
|
||||||
|
// httpdSend(connData, FIRMWARE_VERSION, -1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
@ -1,189 +0,0 @@ |
|||||||
#include <esp8266.h> |
|
||||||
#include <httpd.h> |
|
||||||
#include "page_monitoring.h" |
|
||||||
#include "reporting.h" |
|
||||||
#include "ftoa.h" |
|
||||||
|
|
||||||
|
|
||||||
httpd_cgi_state FLASH_FN cgiMonCompare(HttpdConnData *connData) |
|
||||||
{ |
|
||||||
if (connData->conn == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
httpdStartResponse(connData, 200); |
|
||||||
httpdHeader(connData, "Content-Type", "application/json"); |
|
||||||
httpdEndHeaders(connData); |
|
||||||
|
|
||||||
// this is semi-async (waits for completion)
|
|
||||||
bool suc = capture_and_report(false); |
|
||||||
|
|
||||||
char buf[100]; |
|
||||||
|
|
||||||
if (suc && rpt_result.ready) { |
|
||||||
// success
|
|
||||||
char *bb = buf; |
|
||||||
bb += sprintf(bb, "{\"success\": true, \"deviation\": "); |
|
||||||
bb += my_ftoa(bb,rpt_result.deviation, 2); |
|
||||||
bb += sprintf(bb, ", \"rms\": "); |
|
||||||
bb += my_ftoa(bb,rpt_result.i_rms, 2); |
|
||||||
bb += sprintf(bb, "}"); |
|
||||||
|
|
||||||
httpdSend(connData, buf, -1); |
|
||||||
} else { |
|
||||||
httpdSend(connData, "{\"success\": false}", -1); |
|
||||||
} |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
/** This is an automated poll for current state, to update the display (measured by reporting func) */ |
|
||||||
httpd_cgi_state FLASH_FN cgiMonStatus(HttpdConnData *connData) |
|
||||||
{ |
|
||||||
if (connData->conn == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
httpdStartResponse(connData, 200); |
|
||||||
httpdHeader(connData, "Content-Type", "application/json"); |
|
||||||
httpdEndHeaders(connData); |
|
||||||
|
|
||||||
char buf[100]; |
|
||||||
|
|
||||||
if (rpt_result.ready) { |
|
||||||
// success
|
|
||||||
char *bb = buf; |
|
||||||
bb += sprintf(bb, "{\"success\": true, \"deviation\": "); |
|
||||||
bb += my_ftoa(bb,rpt_result.deviation, 2); |
|
||||||
bb += sprintf(bb, ", \"rms\": "); |
|
||||||
bb += my_ftoa(bb,rpt_result.i_rms, 2); |
|
||||||
bb += sprintf(bb, "}"); |
|
||||||
httpdSend(connData, buf, -1); |
|
||||||
} else { |
|
||||||
httpdSend(connData, "{\"success\": false}", -1); |
|
||||||
} |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
httpd_cgi_state FLASH_FN cgiMonSetRef(HttpdConnData *connData) |
|
||||||
{ |
|
||||||
if (connData->conn == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
httpdStartResponse(connData, 200); |
|
||||||
httpdHeader(connData, "Content-Type", "application/json"); |
|
||||||
httpdEndHeaders(connData); |
|
||||||
|
|
||||||
// this is semi-async (waits for completion)
|
|
||||||
bool suc = capture_reporting_reference(); |
|
||||||
httpdSend(connData, suc ? "{\"success\": true}" : "{\"success\": false}", -1); |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
httpd_cgi_state FLASH_FN cgiMonitoringCfg(HttpdConnData *connData) |
|
||||||
{ |
|
||||||
if (connData->conn == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
// TODO
|
|
||||||
HttpdPostData *post = connData->post; |
|
||||||
if (post != NULL) { |
|
||||||
char buf[64]; |
|
||||||
int blen; |
|
||||||
|
|
||||||
// enabled=1
|
|
||||||
blen = httpdFindArg(post->buff, "enabled", buf, 64); |
|
||||||
if (blen == -1) { |
|
||||||
// wasn't found
|
|
||||||
rpt_conf.enabled = false; |
|
||||||
} else { |
|
||||||
rpt_conf.enabled = (buf[0] == '1'); |
|
||||||
} |
|
||||||
|
|
||||||
// interval=secs
|
|
||||||
blen = httpdFindArg(post->buff, "interval", buf, 64); |
|
||||||
if (blen != -1) { |
|
||||||
rpt_conf.interval = (uint32_t)atoi(buf); |
|
||||||
} |
|
||||||
|
|
||||||
// service=xv or ts
|
|
||||||
blen = httpdFindArg(post->buff, "service", buf, 64); |
|
||||||
if (blen != -1) { |
|
||||||
rpt_conf.service = (buf[0] == 'x' ? RPT_XIVELY: RPT_THINGSPEAK); |
|
||||||
} |
|
||||||
|
|
||||||
// feed
|
|
||||||
blen = httpdFindArg(post->buff, "feed", buf, 64); |
|
||||||
if (blen != -1) { |
|
||||||
strcpy(rpt_conf.feed, buf); |
|
||||||
} |
|
||||||
|
|
||||||
// key
|
|
||||||
blen = httpdFindArg(post->buff, "key", buf, 64); |
|
||||||
if (blen != -1) { |
|
||||||
strcpy(rpt_conf.key, buf); |
|
||||||
} |
|
||||||
|
|
||||||
// Save & Apply
|
|
||||||
reporting_cfg_save(); |
|
||||||
} |
|
||||||
|
|
||||||
httpdRedirect(connData, "/monitoring"); |
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** "Monitoring" page - fill form fields */ |
|
||||||
httpd_cgi_state FLASH_FN tplMonitoring(HttpdConnData *connData, char *token, void **arg) |
|
||||||
{ |
|
||||||
(void)arg; |
|
||||||
|
|
||||||
char buf[20]; |
|
||||||
|
|
||||||
if (token == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
if (streq(token, "refStored")) { |
|
||||||
httpdSend(connData, true ? "OK" : "Not set!", -1); // fixme
|
|
||||||
|
|
||||||
} else if (streq(token, "curDeviation")) { |
|
||||||
// current deviation
|
|
||||||
if (rpt_result.ready) { |
|
||||||
my_ftoa(buf, rpt_result.deviation, 2); |
|
||||||
} else { |
|
||||||
sprintf(buf, "--"); |
|
||||||
} |
|
||||||
httpdSend(connData, buf, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "curRMS")) { |
|
||||||
// current deviation
|
|
||||||
if (rpt_result.ready) { |
|
||||||
my_ftoa(buf, rpt_result.i_rms, 2); |
|
||||||
} else { |
|
||||||
sprintf(buf, "--"); |
|
||||||
} |
|
||||||
httpdSend(connData, buf, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "rep_en")) { |
|
||||||
if (rpt_conf.enabled) httpdSend(connData, "checked", -1); |
|
||||||
|
|
||||||
} else if (streq(token, "repInterval")) { // interval in seconds
|
|
||||||
sprintf(buf, "%d", rpt_conf.interval); |
|
||||||
httpdSend(connData, buf, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "svc_xv")) { // Xively checkbox
|
|
||||||
if (rpt_conf.service == RPT_XIVELY) { |
|
||||||
httpdSend(connData, "checked", -1); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (streq(token, "svc_ts")) { // ThingSpeak checkbox
|
|
||||||
if (rpt_conf.service == RPT_THINGSPEAK) { |
|
||||||
httpdSend(connData, "checked", -1); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (streq(token, "repFeed")) { // reporting feed ID
|
|
||||||
httpdSend(connData, rpt_conf.feed, -1); |
|
||||||
|
|
||||||
} else if (streq(token, "repKey")) { // reporting key
|
|
||||||
httpdSend(connData, rpt_conf.key, -1); |
|
||||||
} |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
#ifndef PAGE_MONITORING_H |
|
||||||
#define PAGE_MONITORING_H |
|
||||||
|
|
||||||
#include <httpd.h> |
|
||||||
|
|
||||||
httpd_cgi_state tplMonitoring(HttpdConnData *connData, char *token, void **arg); |
|
||||||
|
|
||||||
httpd_cgi_state cgiMonCompare(HttpdConnData *connData); |
|
||||||
httpd_cgi_state cgiMonStatus(HttpdConnData *connData); // same result as "compare", but doesn't measure anything
|
|
||||||
|
|
||||||
httpd_cgi_state cgiMonSetRef(HttpdConnData *connData); |
|
||||||
|
|
||||||
httpd_cgi_state cgiMonitoringCfg(HttpdConnData *connData); |
|
||||||
|
|
||||||
#endif // PAGE_MONITORING_H
|
|
@ -1,159 +0,0 @@ |
|||||||
#include <esp8266.h> |
|
||||||
#include <httpd.h> |
|
||||||
#include "page_status.h" |
|
||||||
#include "uptime.h" |
|
||||||
|
|
||||||
#include "utils.h" |
|
||||||
|
|
||||||
|
|
||||||
/** System Status page */ |
|
||||||
httpd_cgi_state FLASH_FN tplSystemStatus(HttpdConnData *connData, char *token, void **arg) |
|
||||||
{ |
|
||||||
// arg is unused
|
|
||||||
(void)arg; |
|
||||||
|
|
||||||
struct station_config stconf; |
|
||||||
struct softap_config apconf; |
|
||||||
|
|
||||||
char buff[300]; |
|
||||||
u8 mac[6]; |
|
||||||
int rssi; |
|
||||||
|
|
||||||
// empty string if no token matches
|
|
||||||
buff[0] = 0; |
|
||||||
|
|
||||||
if (token == NULL) return HTTPD_CGI_DONE; |
|
||||||
|
|
||||||
|
|
||||||
// {
|
|
||||||
// "uptime": "00:01:1200:01:12",
|
|
||||||
// "heap": 3391233912,
|
|
||||||
// "wifiMode": "ClientClient",
|
|
||||||
// "sta": null,
|
|
||||||
// "ap": {"SSID": "ESP_D58987", "pwd": "", "MAC": "1a:fe:34:d5:89:87", "chan": 1, "hidden": false, "auth": Open, }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int opmode = wifi_get_opmode(); |
|
||||||
bool is_sta = (opmode == STATION_MODE || opmode == STATIONAP_MODE); |
|
||||||
bool is_ap = (opmode == SOFTAP_MODE || opmode == STATIONAP_MODE); |
|
||||||
|
|
||||||
if (streq(token, "uptime")) { |
|
||||||
// Uptime
|
|
||||||
uptime_str(buff); |
|
||||||
|
|
||||||
} else if (streq(token, "heap")) { |
|
||||||
// Free heap
|
|
||||||
sprintf(buff, "%u", system_get_free_heap_size()); |
|
||||||
|
|
||||||
} else if (streq(token, "wifiMode")) { |
|
||||||
// WiFi mode
|
|
||||||
strcpy(buff, opmode2str(opmode)); |
|
||||||
|
|
||||||
} else if (streq(token, "staInfo")) { |
|
||||||
if (!is_sta) { |
|
||||||
strcpy(buff, "null"); |
|
||||||
} else { |
|
||||||
// AP info
|
|
||||||
wifi_station_get_config(&stconf); |
|
||||||
wifi_get_macaddr(STATION_IF, mac); |
|
||||||
rssi = wifi_station_get_rssi(); |
|
||||||
|
|
||||||
sprintf(buff, |
|
||||||
"{" |
|
||||||
"\"SSID\": \"%s\", " |
|
||||||
"\"RSSI\": %d, " |
|
||||||
"\"RSSIperc\": %d, " |
|
||||||
"\"MAC\": \""MACSTR"\"" |
|
||||||
"}", |
|
||||||
stconf.ssid, |
|
||||||
rssi, |
|
||||||
rssi2perc(rssi), |
|
||||||
MAC2STR(mac) |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (streq(token, "apInfo")) { |
|
||||||
if (!is_ap) { |
|
||||||
strcpy(buff, "null"); |
|
||||||
} else { |
|
||||||
wifi_softap_get_config(&apconf); |
|
||||||
wifi_get_macaddr(SOFTAP_IF, mac); |
|
||||||
|
|
||||||
// AP info
|
|
||||||
sprintf(buff, |
|
||||||
"{" |
|
||||||
"\"SSID\": \"%s\", " |
|
||||||
"\"pwd\": \"%s\", " |
|
||||||
"\"MAC\": \""MACSTR"\", " |
|
||||||
"\"chan\": %d, " |
|
||||||
"\"hidden\": %s, " |
|
||||||
"\"auth\": \"%s\"" |
|
||||||
"}", |
|
||||||
apconf.ssid, |
|
||||||
apconf.password, |
|
||||||
MAC2STR(mac), |
|
||||||
apconf.channel, |
|
||||||
apconf.ssid_hidden ? "true" : "false", |
|
||||||
auth2str(apconf.authmode) |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
/*} else if (streq(token, "staSSID")) {
|
|
||||||
// Station SSID (if in station mode)
|
|
||||||
if (!is_sta) { |
|
||||||
strcpy(buff, "N/A"); |
|
||||||
} else { |
|
||||||
strcpy(buff, (char*)stconf.ssid); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (streq(token, "staRSSI")) { |
|
||||||
// Signal strength if in Station mode
|
|
||||||
if (!is_sta) { |
|
||||||
strcpy(buff, "0"); |
|
||||||
} else { |
|
||||||
rssi = wifi_station_get_rssi(); |
|
||||||
sprintf(buff, "%d", rssi); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (streq(token, "staRSSIperc")) { |
|
||||||
// Signal strength if in Station mode
|
|
||||||
if (!is_sta) { |
|
||||||
strcpy(buff, "0"); |
|
||||||
} else { |
|
||||||
rssi = wifi_station_get_rssi(); |
|
||||||
sprintf(buff, "%d", rssi2perc(rssi)); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (streq(token, "staMAC")) { |
|
||||||
// Station MAC addr
|
|
||||||
wifi_get_macaddr(STATION_IF, mac); |
|
||||||
sprintf(buff, MACSTR, MAC2STR(mac)); |
|
||||||
|
|
||||||
} else if (streq(token, "apMAC")) { |
|
||||||
// SoftAP MAC addr
|
|
||||||
wifi_get_macaddr(SOFTAP_IF, mac); |
|
||||||
sprintf(buff, MACSTR, MAC2STR(mac)); |
|
||||||
|
|
||||||
} else if (streq(token, "chipID")) { |
|
||||||
// Chip serial number
|
|
||||||
sprintf(buff, "%08x", system_get_chip_id());*/ |
|
||||||
} |
|
||||||
|
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
"sta": { |
|
||||||
"SSID": "%staSSID%", |
|
||||||
"RSSI": %staRSSI%, |
|
||||||
"RSSIperc": %staRSSIperc%, |
|
||||||
"MAC": "%staMAC%" |
|
||||||
}, |
|
||||||
"ap": { |
|
||||||
"MAC": "%apMAC%" |
|
||||||
}, |
|
||||||
*/ |
|
@ -1,8 +0,0 @@ |
|||||||
#ifndef PAGE_HOME_H |
|
||||||
#define PAGE_HOME_H |
|
||||||
|
|
||||||
#include <httpd.h> |
|
||||||
|
|
||||||
httpd_cgi_state tplSystemStatus(HttpdConnData *connData, char *token, void **arg); |
|
||||||
|
|
||||||
#endif // PAGE_HOME_H
|
|
@ -1,191 +0,0 @@ |
|||||||
#include <esp8266.h> |
|
||||||
#include <httpd.h> |
|
||||||
#include "page_waveform.h" |
|
||||||
|
|
||||||
#include "ftoa.h" |
|
||||||
#include "sampling.h" |
|
||||||
#include "serial.h" |
|
||||||
#include "payload_parser.h" |
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Read multiple samples from the ADC as JSON
|
|
||||||
|
|
||||||
typedef struct { |
|
||||||
uint16_t total_count; |
|
||||||
uint16_t done_count; |
|
||||||
uint32_t freq; |
|
||||||
bool success; |
|
||||||
} tplReadSamplesJSON_state; |
|
||||||
|
|
||||||
|
|
||||||
static httpd_cgi_state FLASH_FN tplSamplesJSON(MEAS_FORMAT fmt, HttpdConnData *connData, char *token, void **arg); |
|
||||||
|
|
||||||
|
|
||||||
httpd_cgi_state FLASH_FN tplWaveformJSON(HttpdConnData *connData, char *token, void **arg) |
|
||||||
{ |
|
||||||
return tplSamplesJSON(RAW, connData, token, arg); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
httpd_cgi_state FLASH_FN tplFourierJSON(HttpdConnData *connData, char *token, void **arg) |
|
||||||
{ |
|
||||||
return tplSamplesJSON(FFT, connData, token, arg); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
static httpd_cgi_state FLASH_FN tplSamplesJSON(MEAS_FORMAT fmt, HttpdConnData *connData, char *token, void **arg) |
|
||||||
{ |
|
||||||
char buff[128]; |
|
||||||
int len; |
|
||||||
|
|
||||||
tplReadSamplesJSON_state *st = *arg; |
|
||||||
|
|
||||||
if (token == NULL) { |
|
||||||
// end of template, or connection closed.
|
|
||||||
if (st != NULL) free(st); |
|
||||||
|
|
||||||
// make sure resources are freed
|
|
||||||
if (!meas_is_closed()) { |
|
||||||
meas_close(); |
|
||||||
} |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; // cleanup
|
|
||||||
} |
|
||||||
|
|
||||||
if (st == NULL) { |
|
||||||
// first call - allocate the struct
|
|
||||||
st = malloc(sizeof(tplReadSamplesJSON_state)); |
|
||||||
*arg = st; |
|
||||||
|
|
||||||
// check how many samples are requested
|
|
||||||
uint16_t count = 1; |
|
||||||
len = httpdFindArg(connData->getArgs, "n", buff, sizeof(buff)); |
|
||||||
if (len != -1) count = (uint16_t)atoi(buff); |
|
||||||
if (count == 0) { |
|
||||||
error("Count == 0"); |
|
||||||
st->success = false; |
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t freq = 0; |
|
||||||
len = httpdFindArg(connData->getArgs, "fs", buff, sizeof(buff)); |
|
||||||
if (len != -1) freq = (uint32_t)atoi(buff); |
|
||||||
if (freq == 0) { |
|
||||||
error("Freq == 0"); |
|
||||||
st->success = false; |
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
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.
|
|
||||||
st->success = meas_request_data(fmt, count, freq); |
|
||||||
if (!st->success) { |
|
||||||
error("Failed to start sampling"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// the "success" field is after the data,
|
|
||||||
// so if readout fails, success can be set to false.
|
|
||||||
|
|
||||||
if (strcmp(token, "values") == 0) { |
|
||||||
if (!st->success) { |
|
||||||
// failed to start sampling
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
// Wait for a chunk
|
|
||||||
|
|
||||||
uint8_t *chunk = NULL; |
|
||||||
uint16_t chunk_len = 0; |
|
||||||
|
|
||||||
// 10 secs or 100 ms - longer wait for intial data.
|
|
||||||
|
|
||||||
if (!meas_wait_for_chunk()) { |
|
||||||
// meas session was already closed.
|
|
||||||
st->success = false; |
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
chunk = meas_get_chunk(&chunk_len); |
|
||||||
|
|
||||||
PayloadParser pp = pp_start(chunk, chunk_len); |
|
||||||
|
|
||||||
// chunk of data...
|
|
||||||
for (; pp.ptr < pp.len; st->done_count++) { |
|
||||||
// preceding comma if not the first number
|
|
||||||
if (st->done_count > 0) { |
|
||||||
httpdSend(connData, ", ", 2); |
|
||||||
} |
|
||||||
|
|
||||||
float samp = pp_float(&pp); |
|
||||||
my_ftoa(buff, samp, 3); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
} |
|
||||||
|
|
||||||
// wait for more data in this % tag
|
|
||||||
if (!meas_is_last_chunk()) { |
|
||||||
meas_request_next_chunk(); |
|
||||||
return HTTPD_CGI_MORE; // more numbers to come
|
|
||||||
} else { |
|
||||||
// we're done
|
|
||||||
meas_close(); |
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
} else if (strcmp(token, "stats") == 0) { |
|
||||||
|
|
||||||
// the STATS json block
|
|
||||||
if (!st->success) { |
|
||||||
httpdSend(connData, "null", 4); |
|
||||||
} else { |
|
||||||
// no %f in sprintf :(
|
|
||||||
|
|
||||||
MeasStats *stats = meas_get_stats(); |
|
||||||
httpdSend(connData, "{", 1); |
|
||||||
|
|
||||||
sprintf(buff, "\"count\": %d, ", stats->count); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
httpdSend(connData, "\"freq\": ", -1); |
|
||||||
my_ftoa(buff, stats->freq, 3); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
httpdSend(connData, ", \"min\": ", -1); |
|
||||||
my_ftoa(buff, stats->min, 3); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
httpdSend(connData, ", \"max\": ", -1); |
|
||||||
my_ftoa(buff, stats->max, 3); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
httpdSend(connData, ", \"rms\": ", -1); |
|
||||||
my_ftoa(buff, stats->rms, 3); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
if (fmt == FFT) { |
|
||||||
// ... maybe something special for fft ...
|
|
||||||
} |
|
||||||
|
|
||||||
sprintf(buff, ", \"format\": \"%s\"", fmt == RAW ? "RAW" : fmt == FFT ? "FFT" : "UNKNOWN"); |
|
||||||
httpdSend(connData, buff, -1); |
|
||||||
|
|
||||||
httpdSend(connData, "}", 1); |
|
||||||
} |
|
||||||
|
|
||||||
} else if (strcmp(token, "success") == 0) { |
|
||||||
// success status
|
|
||||||
httpdSend(connData, (st->success ? "true" : "false"), -1); |
|
||||||
} |
|
||||||
|
|
||||||
return HTTPD_CGI_DONE; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,10 +0,0 @@ |
|||||||
#ifndef PAGE_WAVEFORM_H |
|
||||||
#define PAGE_WAVEFORM_H |
|
||||||
|
|
||||||
#include <httpd.h> |
|
||||||
|
|
||||||
httpd_cgi_state tplWaveformJSON(HttpdConnData *connData, char *token, void **arg); |
|
||||||
|
|
||||||
httpd_cgi_state tplFourierJSON(HttpdConnData *connData, char *token, void **arg); |
|
||||||
|
|
||||||
#endif // PAGE_WAVEFORM_H
|
|
@ -0,0 +1,40 @@ |
|||||||
|
#include "pers_cfg.h" |
||||||
|
#include "datalink.h" |
||||||
|
#include "serial.h" |
||||||
|
#include "httpclient.h" |
||||||
|
#include "ftoa.h" |
||||||
|
|
||||||
|
#define RPT_CONF_MAGIC 0x24C595D5 |
||||||
|
|
||||||
|
PersistentCfg pers_conf; |
||||||
|
|
||||||
|
/** Save reporting config to flash */ |
||||||
|
void FLASH_FN persistent_cfg_save(void) |
||||||
|
{ |
||||||
|
info("Saving persistent user config"); |
||||||
|
|
||||||
|
system_param_save_with_protect(0x3D, &pers_conf, sizeof(PersistentCfg)); |
||||||
|
|
||||||
|
info("Config saved."); |
||||||
|
} |
||||||
|
|
||||||
|
/** Load the reporting config from flash */ |
||||||
|
void FLASH_FN persistent_cfg_load(void) |
||||||
|
{ |
||||||
|
info("Loading persistent user config"); |
||||||
|
|
||||||
|
system_param_load(0x3D, 0, &pers_conf, sizeof(PersistentCfg)); |
||||||
|
|
||||||
|
if (pers_conf.magic != RPT_CONF_MAGIC) { |
||||||
|
warn("Config block corrupted, reset to defaults."); |
||||||
|
|
||||||
|
// invalid config, zero out
|
||||||
|
memset(&pers_conf, 0, sizeof(PersistentCfg)); |
||||||
|
pers_conf.magic = RPT_CONF_MAGIC; |
||||||
|
|
||||||
|
// save fixed
|
||||||
|
persistent_cfg_save(); |
||||||
|
} |
||||||
|
|
||||||
|
info("Config loaded."); |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
#ifndef REPORTING_H |
||||||
|
#define REPORTING_H |
||||||
|
|
||||||
|
#include <esp8266.h> |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
uint32_t magic; |
||||||
|
} PersistentCfg; |
||||||
|
|
||||||
|
|
||||||
|
/** Reporting config struct */ |
||||||
|
extern PersistentCfg pers_conf; |
||||||
|
|
||||||
|
/** Save reporting config to flash */ |
||||||
|
void persistent_cfg_save(void); |
||||||
|
|
||||||
|
/** Load the reporting config from flash */ |
||||||
|
void persistent_cfg_load(void); |
||||||
|
|
||||||
|
#endif // REPORTING_H
|
@ -1,259 +0,0 @@ |
|||||||
#include "reporting.h" |
|
||||||
#include "datalink.h" |
|
||||||
#include "serial.h" |
|
||||||
#include "httpclient.h" |
|
||||||
#include "ftoa.h" |
|
||||||
|
|
||||||
#define RPT_CONF_MAGIC 0x24C595D5 |
|
||||||
|
|
||||||
ReportingResult rpt_result; |
|
||||||
ReportingCfg rpt_conf; |
|
||||||
|
|
||||||
static os_timer_t rpt_tim; |
|
||||||
|
|
||||||
/** Timer cb */ |
|
||||||
static void FLASH_FN rpt_tim_cb(void *arg) |
|
||||||
{ |
|
||||||
(void)arg; |
|
||||||
// send report now...
|
|
||||||
if (rpt_conf.enabled) { |
|
||||||
capture_and_report(true); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** Stop / start timer & set interval based on rpt conf */ |
|
||||||
static FLASH_FN void set_timer(void) |
|
||||||
{ |
|
||||||
os_timer_disarm(&rpt_tim); |
|
||||||
|
|
||||||
if (rpt_conf.enabled) { |
|
||||||
os_timer_setfn(&rpt_tim, rpt_tim_cb, NULL); |
|
||||||
os_timer_arm(&rpt_tim, (int)(rpt_conf.interval * 1000), 1); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** Fix unterminated strings, add magic, etc.. */ |
|
||||||
static FLASH_FN void normalize_rpt_conf(void) |
|
||||||
{ |
|
||||||
// terminate strings
|
|
||||||
rpt_conf.feed[sizeof(rpt_conf.feed) - 1] = 0; |
|
||||||
rpt_conf.key[sizeof(rpt_conf.key) - 1] = 0; |
|
||||||
// set magic
|
|
||||||
rpt_conf.magic = RPT_CONF_MAGIC; |
|
||||||
} |
|
||||||
|
|
||||||
static FLASH_FN void dump_rpt_conf(void) |
|
||||||
{ |
|
||||||
dbg("Enabled: %d | Interval: %d | Service: %s", rpt_conf.enabled, rpt_conf.interval, (rpt_conf.service == RPT_XIVELY ? "Xively" : "ThingSpeak")); |
|
||||||
dbg("Key: %s | Feed: %s", rpt_conf.key, rpt_conf.feed); |
|
||||||
} |
|
||||||
|
|
||||||
/** Save reporting config to flash */ |
|
||||||
void FLASH_FN reporting_cfg_save(void) |
|
||||||
{ |
|
||||||
normalize_rpt_conf(); // fix weirdness
|
|
||||||
|
|
||||||
info("Saving monitoring config"); |
|
||||||
dump_rpt_conf(); |
|
||||||
|
|
||||||
system_param_save_with_protect(0x3D, &rpt_conf, sizeof(ReportingCfg)); |
|
||||||
|
|
||||||
// start timer for the new interval time
|
|
||||||
set_timer(); |
|
||||||
|
|
||||||
info("Config saved."); |
|
||||||
} |
|
||||||
|
|
||||||
/** Load the reporting config from flash */ |
|
||||||
void FLASH_FN reporting_cfg_load(void) |
|
||||||
{ |
|
||||||
info("Loading monitoring config"); |
|
||||||
|
|
||||||
system_param_load(0x3D, 0, &rpt_conf, sizeof(ReportingCfg)); |
|
||||||
|
|
||||||
if (rpt_conf.magic != RPT_CONF_MAGIC) { |
|
||||||
warn("Config block corrupted, reset to defaults."); |
|
||||||
|
|
||||||
// invalid config, zero out
|
|
||||||
memset(&rpt_conf, 0, sizeof(ReportingCfg)); |
|
||||||
rpt_conf.magic = RPT_CONF_MAGIC; |
|
||||||
|
|
||||||
// save fixed
|
|
||||||
reporting_cfg_save(); |
|
||||||
} else { |
|
||||||
dump_rpt_conf(); |
|
||||||
} |
|
||||||
|
|
||||||
set_timer(); |
|
||||||
|
|
||||||
info("Config loaded."); |
|
||||||
} |
|
||||||
|
|
||||||
/** Called when response to Compare Ref is received */ |
|
||||||
static void FLASH_FN compare_ref_cb(SBMP_Endpoint *ep, SBMP_Datagram *dg, void **obj) |
|
||||||
{ |
|
||||||
(void)obj; |
|
||||||
sbmp_ep_remove_listener(ep, dg->session); |
|
||||||
|
|
||||||
info("Measurement complete."); |
|
||||||
|
|
||||||
rpt_result.success = (dg->type == DG_SUCCESS); |
|
||||||
|
|
||||||
if (dg->type == DG_SUCCESS) { |
|
||||||
PayloadParser pp = pp_start(dg->payload, dg->length); |
|
||||||
rpt_result.deviation = pp_float(&pp); |
|
||||||
rpt_result.i_rms = pp_float(&pp); |
|
||||||
} else { |
|
||||||
error("FAIL resp from sbmp."); |
|
||||||
} |
|
||||||
|
|
||||||
rpt_result.ready = true; // signal to waiting loop
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** Send report from rpt_result */ |
|
||||||
static void FLASH_FN do_send_report(void) |
|
||||||
{ |
|
||||||
info("Sending report..."); |
|
||||||
|
|
||||||
char buf[100]; |
|
||||||
char *bb = buf; |
|
||||||
|
|
||||||
char url_buf[200]; |
|
||||||
char hdrs_buf[100]; |
|
||||||
|
|
||||||
switch (rpt_conf.service) { |
|
||||||
case RPT_XIVELY: |
|
||||||
bb += sprintf(bb, "deviation,"); |
|
||||||
bb += my_ftoa(bb, rpt_result.deviation, 2); |
|
||||||
bb += sprintf(bb, "\nI_rms,"); |
|
||||||
bb += my_ftoa(bb, rpt_result.i_rms, 2); |
|
||||||
|
|
||||||
// URL
|
|
||||||
// We technically could use HTTPS, but it's not tested and probably buggy as hell
|
|
||||||
sprintf(url_buf, "http://api.xively.com/v2/feeds/%s.csv", rpt_conf.feed); |
|
||||||
|
|
||||||
// Key
|
|
||||||
sprintf(hdrs_buf, "X-ApiKey: %s\r\n", rpt_conf.key); |
|
||||||
|
|
||||||
http_put(url_buf, buf, hdrs_buf, http_callback_showstatus); |
|
||||||
|
|
||||||
break; |
|
||||||
|
|
||||||
case RPT_THINGSPEAK: |
|
||||||
bb += sprintf(bb, "key=%s", rpt_conf.key); |
|
||||||
bb += sprintf(bb, "&field1="); |
|
||||||
bb += my_ftoa(bb, rpt_result.deviation, 2); |
|
||||||
bb += sprintf(bb, "&field2="); |
|
||||||
bb += my_ftoa(bb, rpt_result.i_rms, 2); |
|
||||||
|
|
||||||
http_post("http://api.thingspeak.com/update", buf, NULL, http_callback_showstatus); |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** Immediately send report to xively / thingspeak */ |
|
||||||
bool FLASH_FN capture_and_report(bool do_report) |
|
||||||
{ |
|
||||||
info("Starting reporting measurmenet..."); |
|
||||||
|
|
||||||
if (rpt_result.busy) { |
|
||||||
error("Capture busy."); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
if (do_report) { |
|
||||||
// don't report in AP mode
|
|
||||||
WIFI_MODE mode = wifi_get_opmode(); |
|
||||||
if (mode != STATION_MODE && mode != STATIONAP_MODE) { |
|
||||||
warn("Not in station mode, cannot report."); |
|
||||||
do_report = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
rpt_result.ready = false; |
|
||||||
rpt_result.busy = true; |
|
||||||
|
|
||||||
uint16_t sesn; |
|
||||||
sbmp_ep_send_message(dlnk_ep, DG_REQUEST_COMPARE_REF, NULL, 0, &sesn, NULL); |
|
||||||
sbmp_ep_add_listener(dlnk_ep, sesn, compare_ref_cb, NULL); |
|
||||||
|
|
||||||
// poll & wait for response
|
|
||||||
const int timeout = 500; |
|
||||||
for (uint32_t i = 0; i < timeout * 100; i++) { |
|
||||||
uart_poll(); |
|
||||||
|
|
||||||
if (rpt_result.ready) { |
|
||||||
if (rpt_result.success && do_report) { |
|
||||||
do_send_report(); |
|
||||||
} |
|
||||||
|
|
||||||
rpt_result.busy = false; |
|
||||||
return true; // done
|
|
||||||
} |
|
||||||
|
|
||||||
os_delay_us(10); |
|
||||||
system_soft_wdt_feed(); // Feed the dog, or it'll bite.
|
|
||||||
} |
|
||||||
|
|
||||||
// timeout - remove listener
|
|
||||||
error("Measure timeout - no resp received."); |
|
||||||
sbmp_ep_remove_listener(dlnk_ep, sesn); |
|
||||||
|
|
||||||
rpt_result.busy = false; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
static bool capt_ref_done; |
|
||||||
static bool capt_ref_success; |
|
||||||
|
|
||||||
/** Callback for "store ref" */ |
|
||||||
static void FLASH_FN store_ref_cb(SBMP_Endpoint *ep, SBMP_Datagram *dg, void **obj) |
|
||||||
{ |
|
||||||
(void)obj; |
|
||||||
sbmp_ep_remove_listener(ep, dg->session); |
|
||||||
|
|
||||||
capt_ref_done = true; |
|
||||||
capt_ref_success = (dg->type == DG_SUCCESS); |
|
||||||
} |
|
||||||
|
|
||||||
/** Capture reference vector for monitoring */ |
|
||||||
bool FLASH_FN capture_reporting_reference(void) |
|
||||||
{ |
|
||||||
info("Capturing reference..."); |
|
||||||
|
|
||||||
if (rpt_result.busy) { |
|
||||||
error("Capture busy."); |
|
||||||
return false; |
|
||||||
} |
|
||||||
rpt_result.busy = true; |
|
||||||
|
|
||||||
uint16_t sesn; |
|
||||||
sbmp_ep_send_message(dlnk_ep, DG_REQUEST_STORE_REF, NULL, 0, &sesn, NULL); |
|
||||||
sbmp_ep_add_listener(dlnk_ep, sesn, store_ref_cb, NULL); |
|
||||||
|
|
||||||
capt_ref_done = false; |
|
||||||
capt_ref_success = false; |
|
||||||
|
|
||||||
const int timeout = 500; |
|
||||||
for (uint32_t i = 0; i < timeout * 100; i++) { |
|
||||||
uart_poll(); |
|
||||||
|
|
||||||
if (capt_ref_done) { |
|
||||||
rpt_result.busy = false; |
|
||||||
return capt_ref_success; // done
|
|
||||||
} |
|
||||||
|
|
||||||
os_delay_us(10); |
|
||||||
system_soft_wdt_feed(); // Feed the dog, or it'll bite.
|
|
||||||
} |
|
||||||
|
|
||||||
// timeout - remove listener
|
|
||||||
error("Ref capture timeout - no resp received."); |
|
||||||
sbmp_ep_remove_listener(dlnk_ep, sesn); |
|
||||||
rpt_result.busy = false; |
|
||||||
return false; |
|
||||||
} |
|
@ -1,52 +0,0 @@ |
|||||||
#ifndef REPORTING_H |
|
||||||
#define REPORTING_H |
|
||||||
|
|
||||||
#include <esp8266.h> |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
// 0
|
|
||||||
bool enabled; |
|
||||||
// 4
|
|
||||||
uint32_t interval; |
|
||||||
// 8
|
|
||||||
enum { |
|
||||||
RPT_XIVELY, |
|
||||||
RPT_THINGSPEAK |
|
||||||
} service; |
|
||||||
// 12
|
|
||||||
char feed[64]; |
|
||||||
// 76
|
|
||||||
char key[64]; |
|
||||||
// 80
|
|
||||||
uint32_t magic; |
|
||||||
} ReportingCfg; |
|
||||||
|
|
||||||
/** Comapre result is stored here */ |
|
||||||
typedef struct { |
|
||||||
bool ready; |
|
||||||
bool success; |
|
||||||
bool busy; |
|
||||||
float deviation; |
|
||||||
float i_rms; |
|
||||||
} ReportingResult; |
|
||||||
|
|
||||||
/** Report result */ |
|
||||||
extern ReportingResult rpt_result; |
|
||||||
|
|
||||||
/** Reporting config struct */ |
|
||||||
extern ReportingCfg rpt_conf; |
|
||||||
|
|
||||||
|
|
||||||
/** Save reporting config to flash */ |
|
||||||
void reporting_cfg_save(void); |
|
||||||
|
|
||||||
/** Load the reporting config from flash */ |
|
||||||
void reporting_cfg_load(void); |
|
||||||
|
|
||||||
/** Immediately capture & send report to xively / thingspeak (or dont send - just for view) */ |
|
||||||
bool capture_and_report(bool do_report); |
|
||||||
|
|
||||||
/** Capture reference vector for monitoring */ |
|
||||||
bool capture_reporting_reference(void); |
|
||||||
|
|
||||||
#endif // REPORTING_H
|
|
@ -1,277 +0,0 @@ |
|||||||
#include <esp8266.h> |
|
||||||
#include <sbmp.h> |
|
||||||
|
|
||||||
#include "datalink.h" |
|
||||||
#include "sampling.h" |
|
||||||
#include "serial.h" |
|
||||||
|
|
||||||
// The buffer is big enough for 256 data bytes - 4*64
|
|
||||||
|
|
||||||
// chunk size for bulk transfer (must be multiple of 4 - length of uint32 / float)
|
|
||||||
// NOTE: If too large, strange errors can occur (problem with the underlying UART FIFO at high speed)
|
|
||||||
// the FIFO has 128 bytes, and should accomodate ideally the whole frame.
|
|
||||||
#define CHUNK_LEN 100 |
|
||||||
|
|
||||||
|
|
||||||
// Only one readout can happen at a time.
|
|
||||||
|
|
||||||
static struct { |
|
||||||
bool waiting_for_measure; /*!< Still waiting for first data packet */ |
|
||||||
bool pending; /*!< Flag that data is currently being read */ |
|
||||||
uint16_t sesn; /*!< SBMP session of the readout sequence */ |
|
||||||
bool chunk_ready; /*!< Chunk was received and is ready for reading */ |
|
||||||
uint8_t received_chunk[CHUNK_LEN]; /*!< Copy of the latest received chunk of data */ |
|
||||||
uint16_t received_chunk_size; /*!< Size of the chunk in latest_chunk_copy */ |
|
||||||
|
|
||||||
uint32_t est_sampling_time; /*!< Estimated time in millis before data is captured and readout starts */ |
|
||||||
|
|
||||||
uint32_t pos; |
|
||||||
uint32_t total; |
|
||||||
|
|
||||||
MEAS_FORMAT format; /*!< Requested data format */ |
|
||||||
|
|
||||||
// --- data stats ---
|
|
||||||
MeasStats stats; |
|
||||||
} rd; |
|
||||||
|
|
||||||
|
|
||||||
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) + SAMP_RD_TMEO; |
|
||||||
} |
|
||||||
|
|
||||||
/** Wait for one chunk, with possible retries */ |
|
||||||
bool FLASH_FN meas_wait_for_chunk(void) |
|
||||||
{ |
|
||||||
for (int retry_count = 0; retry_count < SAMP_RD_RETRY_COUNT; retry_count++) { |
|
||||||
uint32_t timeout = (rd.waiting_for_measure ? rd.est_sampling_time: SAMP_RD_TMEO); |
|
||||||
// dbg("Chunk read total timeout = %d ms", timeout);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < timeout*100; i++) { |
|
||||||
uart_poll(); // can stop measure & start first chunk, if rx offer
|
|
||||||
|
|
||||||
// check for closed connection - aborted by peer?
|
|
||||||
if (meas_is_closed()) { |
|
||||||
error("Session closed by peer, readout failed."); |
|
||||||
return false; // assume already cleaned up
|
|
||||||
} |
|
||||||
|
|
||||||
if (meas_chunk_ready()) { |
|
||||||
// yay!!
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
os_delay_us(10); |
|
||||||
system_soft_wdt_feed(); // Feed the dog, or it'll bite.
|
|
||||||
} |
|
||||||
|
|
||||||
// Data still not Rx
|
|
||||||
if (rd.waiting_for_measure) { |
|
||||||
|
|
||||||
// only one try in this case
|
|
||||||
error("Sampling aborted due to timeout (no data offered)"); |
|
||||||
sbmp_bulk_abort(dlnk_ep, rd.sesn); // send abort msg
|
|
||||||
meas_close(); // close
|
|
||||||
return false; |
|
||||||
|
|
||||||
} else { |
|
||||||
warn("Data chunk not rx in time."); |
|
||||||
dbg("Requesting again (try %d of %d).", retry_count+1, SAMP_RD_RETRY_COUNT); |
|
||||||
|
|
||||||
sbmp_bulk_request(dlnk_ep, rd.pos, CHUNK_LEN, rd.sesn); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
error("Retry count exhausted!"); |
|
||||||
sbmp_bulk_abort(dlnk_ep, rd.sesn); |
|
||||||
meas_close(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
/** request next chunk */ |
|
||||||
void FLASH_FN meas_request_next_chunk(void) |
|
||||||
{ |
|
||||||
if (!rd.pending) return; |
|
||||||
rd.chunk_ready = false; // invalidate the current chunk, so waiting for chunk is possible.
|
|
||||||
sbmp_bulk_request(dlnk_ep, rd.pos, CHUNK_LEN, rd.sesn); |
|
||||||
} |
|
||||||
|
|
||||||
/** Check if chunk ready to be read */ |
|
||||||
bool FLASH_FN meas_chunk_ready(void) |
|
||||||
{ |
|
||||||
return rd.pending && rd.chunk_ready; |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get received chunk. NULL if none. |
|
||||||
* |
|
||||||
* The array is valid until next chunk is requested. |
|
||||||
* Chunk length in bytes is stored in the argument. |
|
||||||
*/ |
|
||||||
uint8_t FLASH_FN *meas_get_chunk(uint16_t *chunk_len) |
|
||||||
{ |
|
||||||
if (!rd.pending) { |
|
||||||
warn("Meas not pending, cant get chunk"); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
if (!rd.chunk_ready) { |
|
||||||
warn("Rx chunk not ready"); |
|
||||||
return NULL; |
|
||||||
} |
|
||||||
|
|
||||||
*chunk_len = rd.received_chunk_size; |
|
||||||
return rd.received_chunk; |
|
||||||
} |
|
||||||
|
|
||||||
/** Check if this was the last chunk */ |
|
||||||
bool FLASH_FN meas_is_last_chunk(void) |
|
||||||
{ |
|
||||||
return rd.pos >= rd.total; |
|
||||||
} |
|
||||||
|
|
||||||
/** Terminate the readout. */ |
|
||||||
void FLASH_FN meas_close(void) |
|
||||||
{ |
|
||||||
if (!rd.pending) return; // ignore this call
|
|
||||||
|
|
||||||
sbmp_ep_remove_listener(dlnk_ep, rd.sesn); |
|
||||||
rd.pending = false; |
|
||||||
|
|
||||||
info("Transfer closed."); |
|
||||||
} |
|
||||||
|
|
||||||
MeasStats FLASH_FN *meas_get_stats(void) |
|
||||||
{ |
|
||||||
return &rd.stats; |
|
||||||
} |
|
||||||
|
|
||||||
static void FLASH_FN request_data_sesn_listener(SBMP_Endpoint *ep, SBMP_Datagram *dg, void **obj) |
|
||||||
{ |
|
||||||
(void)obj; |
|
||||||
|
|
||||||
// dbg("Received msg in session %d, dg type %d", dg->session, dg->type);
|
|
||||||
|
|
||||||
PayloadParser pp; |
|
||||||
switch (dg->type) { |
|
||||||
case DG_BULK_OFFER:// Data ready notification
|
|
||||||
// data is ready to be read
|
|
||||||
pp = pp_start(dg->payload, dg->length); |
|
||||||
|
|
||||||
rd.pos = 0; |
|
||||||
rd.total = pp_u32(&pp); |
|
||||||
rd.waiting_for_measure = false; // "pending" flag remains set
|
|
||||||
|
|
||||||
// --- here start the user data (common) ---
|
|
||||||
rd.stats.count = pp_u32(&pp); |
|
||||||
rd.stats.freq = pp_float(&pp); |
|
||||||
rd.stats.min = pp_float(&pp); |
|
||||||
rd.stats.max = pp_float(&pp); |
|
||||||
rd.stats.rms = pp_float(&pp); |
|
||||||
// --- user data end ---
|
|
||||||
|
|
||||||
if (rd.format == FFT) { |
|
||||||
// TODO read extra FFT stats ??
|
|
||||||
} |
|
||||||
|
|
||||||
info("Offered %d bytes of data, starting readout.", rd.total); |
|
||||||
|
|
||||||
// request first chunk
|
|
||||||
sbmp_bulk_request(ep, rd.pos, CHUNK_LEN, dg->session); |
|
||||||
break; |
|
||||||
|
|
||||||
case DG_BULK_DATA: // data received
|
|
||||||
// Process the received data
|
|
||||||
memcpy(rd.received_chunk, dg->payload, dg->length); |
|
||||||
rd.chunk_ready = true; |
|
||||||
rd.received_chunk_size = dg->length; |
|
||||||
|
|
||||||
// move the pointer for next request
|
|
||||||
rd.pos += dg->length; |
|
||||||
|
|
||||||
// --- Now we wait for the CGI func to retrieve the chunk and send it to the browser. ---
|
|
||||||
|
|
||||||
if (rd.pos >= rd.total) { |
|
||||||
info("Transfer is complete."); |
|
||||||
// transfer complete
|
|
||||||
|
|
||||||
// ask peer to release the buffer & go idle
|
|
||||||
sbmp_bulk_abort(ep, dg->session); |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
case DG_BULK_ABORT: // Peer resets the readout
|
|
||||||
// this is unlikely
|
|
||||||
warn("Bulk transfer aborted by peer."); |
|
||||||
goto cleanup; |
|
||||||
} |
|
||||||
|
|
||||||
return; |
|
||||||
|
|
||||||
cleanup: |
|
||||||
// remove the listener
|
|
||||||
meas_close(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool FLASH_FN meas_request_data(MEAS_FORMAT format, uint16_t count, uint32_t freq) |
|
||||||
{ |
|
||||||
bool suc = false; |
|
||||||
|
|
||||||
info("Requesting data capture - %d samples @ %d Hz, fmt %d.", count, freq, format); |
|
||||||
|
|
||||||
if (rd.pending) { |
|
||||||
warn("Acquire request already in progress; shouldn't happen, IGNORING"); |
|
||||||
} |
|
||||||
|
|
||||||
if (sbmp_ep_handshake_status(dlnk_ep) != SBMP_HSK_SUCCESS) { |
|
||||||
error("Hsk status not SUCCESS, can't request data."); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
// clean up
|
|
||||||
rd.chunk_ready = false; |
|
||||||
rd.pos = 0; |
|
||||||
rd.total = 0; |
|
||||||
rd.pending = true; |
|
||||||
rd.format = format; |
|
||||||
memset(&rd.stats, 0, sizeof(MeasStats)); // clear the stats obj
|
|
||||||
|
|
||||||
rd.est_sampling_time = meas_estimate_duration(count, freq); |
|
||||||
|
|
||||||
// start a message
|
|
||||||
uint16_t sesn = 0; |
|
||||||
suc = sbmp_ep_start_message(dlnk_ep, format, sizeof(uint16_t)+sizeof(uint32_t), &sesn); // format enum matches the message types
|
|
||||||
if (!suc) goto fail; |
|
||||||
|
|
||||||
// register the session listener
|
|
||||||
suc = sbmp_ep_add_listener(dlnk_ep, sesn, request_data_sesn_listener, NULL); |
|
||||||
if (!suc) { |
|
||||||
// discard the unfinished outgoing packet
|
|
||||||
sbmp_frm_reset_tx(&dlnk_ep->frm); |
|
||||||
goto fail; |
|
||||||
} |
|
||||||
|
|
||||||
rd.sesn = sesn; |
|
||||||
rd.waiting_for_measure = true; // waiting for acquisition module to start sending data
|
|
||||||
|
|
||||||
// request N values
|
|
||||||
sbmp_ep_send_u16(dlnk_ep, count); |
|
||||||
|
|
||||||
// at freq F
|
|
||||||
sbmp_ep_send_u32(dlnk_ep, freq); |
|
||||||
|
|
||||||
dbg("Request sent, session nr %d", sesn); |
|
||||||
|
|
||||||
return true; |
|
||||||
|
|
||||||
fail: |
|
||||||
rd.waiting_for_measure = false; |
|
||||||
rd.pending = false; |
|
||||||
return false; |
|
||||||
} |
|
@ -1,75 +0,0 @@ |
|||||||
#ifndef SAMPLING_H |
|
||||||
#define SAMPLING_H |
|
||||||
|
|
||||||
#include <esp8266.h> |
|
||||||
#include <httpd.h> |
|
||||||
#include "datalink.h" |
|
||||||
|
|
||||||
// ms
|
|
||||||
#define SAMP_RD_TMEO 300 |
|
||||||
#define SAMP_RD_RETRY_COUNT 3 |
|
||||||
#define SAMP_RD_TMEO_TOTAL (SAMP_RD_TMEO*SAMP_RD_RETRY_COUNT+200) |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
uint32_t count; |
|
||||||
float freq; // actual frequency - not exact due to the prescaller limitations
|
|
||||||
float min; |
|
||||||
float max; |
|
||||||
float rms; |
|
||||||
} MeasStats; |
|
||||||
|
|
||||||
typedef enum { |
|
||||||
RAW = DG_REQUEST_RAW, // same as the SBMP packet numbers used to request it
|
|
||||||
FFT = DG_REQUEST_FFT |
|
||||||
} MEAS_FORMAT; |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reading procedure |
|
||||||
* ----------------- |
|
||||||
* |
|
||||||
* 1. meas_request_data(count) |
|
||||||
* 2. wait for meas_chunk_ready() == true |
|
||||||
* 3. meas_get_chunk() to read the chunk last received |
|
||||||
* 4. if meas_is_last_chunk(), call meas_close() and DONE. |
|
||||||
* 5. meas_request_next_chunk() to get more data, goto 2 |
|
||||||
* |
|
||||||
* 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.
|
|
||||||
|
|
||||||
/** request next chunk */ |
|
||||||
void meas_request_next_chunk(void); |
|
||||||
|
|
||||||
/** Check if chunk ready to be read */ |
|
||||||
bool meas_chunk_ready(void); |
|
||||||
|
|
||||||
/** Check if closed (if data was expected, this means the peer aborted the transaction) */ |
|
||||||
bool meas_is_closed(void); |
|
||||||
|
|
||||||
/** Get the stats struct */ |
|
||||||
MeasStats *meas_get_stats(void); |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get received chunk. NULL if none. |
|
||||||
* |
|
||||||
* The array is valid until next chunk is requested. |
|
||||||
* Chunk length in bytes is stored in the argument. |
|
||||||
*/ |
|
||||||
uint8_t *meas_get_chunk(uint16_t *chunk_len); |
|
||||||
|
|
||||||
/** Check if this was the last chunk */ |
|
||||||
bool meas_is_last_chunk(void); |
|
||||||
|
|
||||||
/** Terminate the readout. */ |
|
||||||
void meas_close(void); |
|
||||||
|
|
||||||
/** Wait for one chunk, with possible retries. True = chunk ready, false = failed. */ |
|
||||||
bool meas_wait_for_chunk(void); |
|
||||||
|
|
||||||
#endif // SAMPLING_H
|
|
Loading…
Reference in new issue