From f77caa03f2d408ca3315cec7c86488e96bf56db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Mon, 16 May 2016 01:17:44 +0200 Subject: [PATCH] more crap Former-commit-id: 6c97ad16f16e48f56fea7a007d5d8136c51a268c --- _web-build_do.sh | 7 +- esp_f105motor.pro | 161 ++++++++++ esp_meas.pro | 167 ----------- html/css/app.css | 2 +- html/js/all.js | 4 +- html/pages/about.tpl | 77 ----- html/pages/fft.html | 102 ------- html/pages/home.tpl | 49 ++++ html/pages/monitoring.tpl | 102 ------- html/pages/sgm.html | 79 ----- html/pages/status.tpl | 128 -------- html/pages/wfm.html | 91 ------ html/pages/wifi.tpl | 6 +- html_src/_start.php | 12 +- html_src/css/app.css | 2 +- html_src/gulpfile.js | 11 +- html_src/js-src/lib/chibi.js | 2 +- html_src/js-src/lib/lodash.custom.js | 285 +++++++++++++++++- html_src/js-src/page_home.js | 11 + html_src/js-src/page_mon.js | 91 ------ html_src/js-src/page_spectrogram.js | 356 ----------------------- html_src/js-src/page_status.js | 88 ------ html_src/js-src/page_waveform.js | 271 ----------------- html_src/js/all.js | 4 +- html_src/node_modules.tar.REMOVED.git-id | 1 - html_src/page_about.php | 48 --- html_src/page_fft.php | 73 ----- html_src/page_home.php | 21 ++ html_src/page_monitoring.php | 73 ----- html_src/page_spectrogram.php | 50 ---- html_src/page_status.php | 99 ------- html_src/page_waveform.php | 62 ---- html_src/page_wifi.php | 3 +- html_src/sass/app.scss | 8 +- html_src/sass/layout/_menu.scss | 4 +- html_src/sass/pages/_about.scss | 17 -- html_src/sass/pages/_home.scss | 24 +- html_src/sass/pages/_wfm.scss | 101 ------- html_src/x_page_layout.php | 71 ----- libesphttpd/core/auth.c | 8 +- libesphttpd/include/auth.h | 2 +- libesphttpd/include/esp8266.h | 2 +- libesphttpd/include/logging.h | 2 +- libesphttpd/include/platform.h | 1 + user/datalink.h | 9 +- user/page_about.c | 83 ------ user/page_home.c | 23 ++ user/{page_about.h => page_home.h} | 2 +- user/page_monitoring.c | 189 ------------ user/page_monitoring.h | 15 - user/page_status.c | 159 ---------- user/page_status.h | 8 - user/page_waveform.c | 191 ------------ user/page_waveform.h | 10 - user/pers_cfg.c | 40 +++ user/pers_cfg.h | 23 ++ user/reporting.c | 259 ----------------- user/reporting.h | 52 ---- user/routes.c | 33 +-- user/sampling.c | 277 ------------------ user/sampling.h | 75 ----- user/sbmp_config.h | 2 +- user/user_main.c | 13 +- user/wificontrol.c | 10 +- 64 files changed, 686 insertions(+), 3565 deletions(-) create mode 100644 esp_f105motor.pro delete mode 100644 esp_meas.pro delete mode 100644 html/pages/about.tpl delete mode 100644 html/pages/fft.html create mode 100644 html/pages/home.tpl delete mode 100644 html/pages/monitoring.tpl delete mode 100644 html/pages/sgm.html delete mode 100644 html/pages/status.tpl delete mode 100644 html/pages/wfm.html create mode 100644 html_src/js-src/page_home.js delete mode 100644 html_src/js-src/page_mon.js delete mode 100644 html_src/js-src/page_spectrogram.js delete mode 100644 html_src/js-src/page_status.js delete mode 100644 html_src/js-src/page_waveform.js delete mode 100644 html_src/node_modules.tar.REMOVED.git-id delete mode 100644 html_src/page_about.php delete mode 100644 html_src/page_fft.php create mode 100644 html_src/page_home.php delete mode 100644 html_src/page_monitoring.php delete mode 100644 html_src/page_spectrogram.php delete mode 100644 html_src/page_status.php delete mode 100644 html_src/page_waveform.php delete mode 100644 html_src/sass/pages/_about.scss delete mode 100644 html_src/sass/pages/_wfm.scss delete mode 100644 html_src/x_page_layout.php delete mode 100644 user/page_about.c create mode 100644 user/page_home.c rename user/{page_about.h => page_home.h} (53%) delete mode 100644 user/page_monitoring.c delete mode 100644 user/page_monitoring.h delete mode 100644 user/page_status.c delete mode 100644 user/page_status.h delete mode 100644 user/page_waveform.c delete mode 100644 user/page_waveform.h create mode 100644 user/pers_cfg.c create mode 100644 user/pers_cfg.h delete mode 100644 user/reporting.c delete mode 100644 user/reporting.h delete mode 100644 user/sampling.c delete mode 100644 user/sampling.h diff --git a/_web-build_do.sh b/_web-build_do.sh index 695a0d2..beed8e3 100755 --- a/_web-build_do.sh +++ b/_web-build_do.sh @@ -23,10 +23,5 @@ find "$BLDDIR" -name "*.map" -delete mkdir -p "$BLDDIR/pages" -php "$SRCDIR/page_status.php" > "$BLDDIR/pages/status.tpl" -php "$SRCDIR/page_about.php" > "$BLDDIR/pages/about.tpl" +php "$SRCDIR/page_home.php" > "$BLDDIR/pages/home.tpl" php "$SRCDIR/page_wifi.php" > "$BLDDIR/pages/wifi.tpl" -php "$SRCDIR/page_monitoring.php" > "$BLDDIR/pages/monitoring.tpl" -php "$SRCDIR/page_waveform.php" > "$BLDDIR/pages/wfm.html" # no substitutions, .html allows to gzip it. -php "$SRCDIR/page_fft.php" > "$BLDDIR/pages/fft.html" # same -php "$SRCDIR/page_spectrogram.php" > "$BLDDIR/pages/sgm.html" # same diff --git a/esp_f105motor.pro b/esp_f105motor.pro new file mode 100644 index 0000000..fca36cd --- /dev/null +++ b/esp_f105motor.pro @@ -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 diff --git a/esp_meas.pro b/esp_meas.pro deleted file mode 100644 index d85508f..0000000 --- a/esp_meas.pro +++ /dev/null @@ -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 diff --git a/html/css/app.css b/html/css/app.css index 09d0a23..8040cd9 100644 --- a/html/css/app.css +++ b/html/css/app.css @@ -1 +1 @@ -*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}figure,nav{display:block}canvas,progress{display:inline-block;vertical-align:baseline}[hidden]{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b{font-weight:700}h1,h2{font-size:2em;margin:.67em 0}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,pre{font-family:monospace;font-size:1em}button,input,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}legend{border:0;padding:0}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}.ct-zoom-rect{fill:rgba(200,100,100,.3);stroke:#ff2b12}.ct-axis-title{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ct-axis-title,.ct-label{fill:rgba(255,255,255,.8)}.ct-label{color:rgba(255,255,255,.8);font-size:.75rem;line-height:1}.ct-label.ct-horizontal.ct-start{align-items:flex-end;justify-content:flex-start;text-align:left;text-anchor:start}.ct-label.ct-horizontal.ct-end{align-items:flex-start;justify-content:flex-start;text-align:left;text-anchor:start;transform:translate(-4px) rotate(45deg)}.ct-label.ct-vertical.ct-start{align-items:flex-end;justify-content:flex-end;text-align:right;text-anchor:end;transform:translateY(20%)}.ct-label.ct-vertical.ct-end{align-items:flex-end;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar .ct-label,.ct-chart-line .ct-label{display:flex}.ct-chart-bar .ct-label.ct-horizontal.ct-start{align-items:flex-end;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar .ct-label.ct-horizontal.ct-end{align-items:flex-start;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-start{align-items:flex-end;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-end{align-items:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-start{align-items:center;justify-content:flex-end;text-align:right;text-anchor:end}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-end{align-items:center;justify-content:flex-start;text-align:left;text-anchor:end}.ct-grid{stroke:rgba(255,255,255,.3);stroke-width:1px;stroke-dasharray:2px}.ct-point{stroke-width:4px;stroke-linecap:round}.ct-line{fill:none;stroke-width:2px}.ct-with-area .ct-line{stroke-width:1px}.ct-area{stroke:none;fill-opacity:.3}.ct-bar{fill:none;stroke-width:10px}.ct-series-a .ct-bar,.ct-series-a .ct-line,.ct-series-a .ct-point{stroke:#f05b4f}.ct-series-a .ct-area,.ct-series-a .ct-slice-pie{fill:#f05b4f}.ct-series-b .ct-bar,.ct-series-b .ct-line,.ct-series-b .ct-point{stroke:#6188e2}.ct-series-b .ct-area,.ct-series-b .ct-slice-pie{fill:#6188e2}.ct-series-c .ct-bar,.ct-series-c .ct-line,.ct-series-c .ct-point{stroke:#59922b}.ct-series-c .ct-area,.ct-series-c .ct-slice-pie{fill:#59922b}.ct-series-d .ct-bar,.ct-series-d .ct-line,.ct-series-d .ct-point{stroke:#eacf7d}.ct-series-d .ct-area,.ct-series-d .ct-slice-pie{fill:#eacf7d}.ct-series-e .ct-bar,.ct-series-e .ct-line,.ct-series-e .ct-point{stroke:#a748ca}.ct-series-e .ct-area,.ct-series-e .ct-slice-pie{fill:#a748ca}.ct-wide{display:block;position:relative;width:100%}.ct-wide:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:62.5%}.ct-wide:after{content:"";display:table;clear:both}.ct-wide>svg{display:block;position:absolute;top:0;left:0}.ct-narrow{display:block;position:relative;width:100%}.ct-narrow:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:66.6666666667%}.ct-narrow:after{content:"";display:table;clear:both}.ct-narrow>svg{display:block;position:absolute;top:0;left:0}.center{text-align:center}.invis{visibility:hidden!important}.hidden{display:none!important}.nb{font-weight:400}html{font-family:Arial,sans-serif;color:#D0D0D0;background:#131315}body,html{border:0 none;margin:0;padding:0;text-decoration:none;width:100%;height:100%;overflow:hidden}a,a:link,a:visited{cursor:pointer;color:#5abfff;text-decoration:none}a:hover{color:#5abfff;text-decoration:underline}.chartexport a{background:#3b7299;border-radius:3px;padding:5px;color:#0c171e;text-decoration:none}.chartexport a:hover{background:#4ea6dd}.chartexport a:active{position:relative;top:1px}.chartexport textarea{margin-top:10px;width:100%;height:10em;resize:vertical}#outer{display:flex;position:absolute;width:100%;height:100%;left:0;right:0;top:0;bottom:0;overflow:hidden;flex-direction:row}@media screen and (max-width:544px){#outer{display:block;overflow-y:scroll}}#menu{flex:0 0 15rem;background:#2bab5f}#menu>*{display:block;text-decoration:none;padding:.6180469716rem 1rem;white-space:nowrap;word-wrap:normal;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#menu #brand{color:white;background:#218248;font-size:120%;text-align:center;position:relative;margin-bottom:1rem}@media screen and (max-width:544px){#menu #brand{background:#2bab5f;cursor:pointer}#menu #brand:after{position:absolute;color:rgba(0,0,0,.2);right:1rem;content:'>';top:50%;font-size:120%;font-weight:700;transform:translateY(-50%) rotate(90deg)}}#menu.expanded #brand{background:#218248}@media screen and (max-width:544px){#menu.expanded #brand:after{transform:translateY(-50%) rotate(-90deg)}}#menu a{font-size:130%;color:white;transition:background-color .2s;text-shadow:0 0 5px rgba(0,0,0,.4)}#menu a.selected,#menu a:hover{background:#1bd886;text-shadow:0 0 5px rgba(0,0,0,.6)}#menu a.selected{position:relative;box-shadow:0 0 5px rgba(0,0,0,.5)}#menu a:before{content:"▸";padding-right:.5rem;position:relative;top:-.1rem}@media screen and (max-width:544px){#menu a{display:none}}#menu.expanded a{display:block}@media screen and (min-width:545px) and (max-width:1000px){#menu{flex-basis:10rem}#menu #brand{font-size:95%;margin-bottom:.6180469716rem}#menu a{font-size:105%}#menu>*{padding:.3819820591rem .6180469716rem}}#content{flex-grow:1;position:relative;padding:1rem;overflow-y:auto}@media screen and (max-width:544px){#content{padding:.6180469716rem}}#content>*{margin-left:auto;margin-right:auto}#content h1{text-align:center;font-size:2.2806973457em;margin-top:0;margin-bottom:1rem}#content h2{font-size:1.423828125em;margin-bottom:.6180469716rem}#content td,#content th{padding:.3819820591rem}#content tbody th{text-align:right;width:130px;color:#fff}#loader{position:absolute;right:1.618rem;top:1.618rem;transition:opacity .2s;opacity:0}@media screen and (max-width:544px){#loader{top:1rem;right:1rem}}#loader.show{opacity:1}.Box{display:block;max-width:900px;margin-top:1rem;padding:.6180469716rem 1rem;border-radius:3px;background-color:rgba(255,255,255,.07)}@media screen and (max-width:544px){.Box{margin-top:.6180469716rem}}.Box h2,h1+.Box{margin-top:0}.Box.wide{width:initial;max-width:initial}.Box.medium{max-width:1200px}.Box .Valfield{display:inline-block;min-width:10em}.Modal{position:fixed;width:100%;height:100%;left:0;top:0;right:0;bottom:0;display:flex;justify-content:center;align-items:center;transition:opacity .5s;background:rgba(0,0,0,.65);opacity:0}.Modal.visible{opacity:1}.Modal.hidden{display:none}.Dialog{margin:.6180469716rem;padding:1rem;overflow:hidden;max-width:100%;max-height:100%;flex:0 1 30rem;background:#1c1c1e;border-left:6px solid #217b3a;border-right:6px solid #217b3a;box-shadow:0 0 2px 0 #434349,0 0 6px 0 black;border-radius:6px}.Dialog h1,.Dialog h2{margin-top:0}.Dialog p:last-child{margin-bottom:0}.NotifyMsg{position:fixed;bottom:2.617924rem;padding:.6180469716rem 1rem;left:50%;transform:translate(-50%);-webkit-font-smoothing:subpixel-antialiased;-webkit-transform:translateZ(0) scale(1);background:#37a349;color:white;text-shadow:0 0 2px black;box-shadow:0 0 6px 0 rgba(0,0,0,.6);border-radius:5px;max-width:80%;transition:opacity .5s;opacity:0}.NotifyMsg.error{background:#d03e42}@media screen and (max-width:544px){.NotifyMsg{width:calc(100% - 1rem)}}.NotifyMsg.visible{opacity:1}.NotifyMsg.hidden{display:none}.button,button,input[type=button],input[type=reset],input[type=submit]{text-align:center;cursor:pointer;display:inline-block;border-radius:2px;padding:0 .6em;border:0 none;outline:0 none!important;line-height:1.8em;font-size:1.1em;margin-bottom:3px;min-width:5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-shadow:1.5px 1.5px 2px rgba(0,0,0,.8)}.button:active,button:active,input[type=button]:active,input[type=reset]:active,input[type=submit]:active{position:relative;top:2px}.button.narrow,button.narrow,input[type=button].narrow,input[type=reset].narrow,input[type=submit].narrow{min-width:initial}.btn-green,input[type=submit]{background-color:#2ca94b;box-shadow:0 3px 0 #1d7032;text-decoration:none!important}.btn-green,.btn-green:link,.btn-green:visited,input[type=submit],input[type=submit]:link,input[type=submit]:visited{color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:active,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:active,input[type=submit]:hover{background-color:#28ba5c;color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:hover{box-shadow:0 3px 0 #1a773b}.btn-green:active,input[type=submit]:active{box-shadow:0 1px 0 #1a773b}.btn-red,input[type=reset]{background-color:#D04E51;box-shadow:0 3px 0 #aa2d30;text-decoration:none!important}.btn-red,.btn-red:link,.btn-red:visited,input[type=reset],input[type=reset]:link,input[type=reset]:visited{color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:active,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:active,input[type=reset]:hover{background-color:#d4403f;color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:hover{box-shadow:0 3px 0 #9e2423}.btn-red:active,input[type=reset]:active{box-shadow:0 1px 0 #9e2423}.btn-blue{background-color:#3983cd;box-shadow:0 3px 0 #265f98;text-decoration:none!important}.btn-blue,.btn-blue:link,.btn-blue:visited{color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:active,.btn-blue:hover{background-color:#2076C6;color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:hover{box-shadow:0 3px 0 #154c80}.btn-blue:active{box-shadow:0 1px 0 #154c80}input[type=number],input[type=password],input[type=text],select,textarea{border:0 none;border-bottom:2px solid #217b3a;background-color:#303030;color:#fff;padding:6px;line-height:1em;outline:0 none!important;-moz-outline:0 none!important;font-weight:400}input[type=number]:focus,input[type=number]:hover,input[type=password]:focus,input[type=password]:hover,input[type=text]:focus,input[type=text]:hover,select:focus,select:hover,textarea:focus,textarea:hover{border-bottom-color:#28bc65}input[type=number],input[type=password],input[type=text],textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;cursor:text}textarea{font-family:monospace;line-height:1.2em;display:block}form{border:0 none;margin:0;padding:0;text-decoration:none}input[type=number],input[type=password],input[type=text],label.select-wrap,select,textarea{width:250px}form .Row{vertical-align:middle;margin:14px auto;text-align:left;display:flex;flex-direction:row}form .Row:first-child{margin-top:0}form .Row:last-child{margin-bottom:0}form .Row .spacer{width:130px}@media screen and (max-width:544px){form .Row .spacer{display:none}}form .Row.buttons .button,form .Row.buttons input{margin-right:.6180469716rem}form .Row.centered{justify-content:center}form .Row.message{font-size:1em;text-shadow:1px 1px 3px black;text-align:center}form .Row.message.error{color:crimson}form .Row.message.ok{color:#0fe851}form .Row.separator{padding-top:14px;border-top:2px solid rgba(255,255,255,.1)}form .Row textarea{display:inline-block;vertical-align:top;min-height:10rem;flex-grow:1;resize:vertical}form .Row label{font-weight:700;color:#fff;text-shadow:1px 1px 3px black;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}form .Row .checkbox-wrap,form .Row label{display:inline-block;width:130px;text-align:right;padding:8px;align-self:flex-start}form .Row .checkbox-wrap input[type=checkbox]{margin:auto;width:auto;height:auto}form .Row .checkbox-wrap+label{width:250px;padding-left:0;text-align:left;cursor:pointer}@media screen and (max-width:544px){form .Row{flex-direction:column}form .Row.buttons,form .Row.centered{flex-direction:row}form .Row.buttons{justify-content:center}form .Row.buttons :last-child{margin-right:0}form .Row label{padding-left:0;text-align:left;width:auto}form .Row .checkbox-wrap{order:1;text-align:left;padding-bottom:0;border-radius:.4px;width:auto}form .Row .checkbox-wrap+label{width:auto}form .Row input[type=number],form .Row input[type=password],form .Row input[type=text],form .Row textarea{width:100%}}form span.required{color:red}.RadioGroup{display:inline-block;line-height:1.5em;vertical-align:middle}.RadioGroup label{width:auto;text-align:left;cursor:pointer;font-weight:400}.RadioGroup input[type=radio]{vertical-align:middle;margin:0 0 0 5px}@media screen and (-webkit-min-device-pixel-ratio:0){select{padding-right:18px}}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;line-height:1.2em;padding-right:1em}select:-moz-focusring{color:transparent;text-shadow:0 0 0 #fff}select option{background:#303030}label.select-wrap{position:relative;display:inline!important;margin:0!important;padding:0!important;width:auto!important}label.select-wrap:after{content:'<>';font-family:Consolas,monospace;font-weight:700;color:#28bc65;top:50%;transform:translateY(-50%) rotate(90deg);right:2px;position:absolute;z-index:100;pointer-events:none}#ap-list{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:0;-moz-column-gap:0;column-gap:0;margin:0 -.2360828548rem}@media screen and (min-width:545px) and (max-width:1000px){#ap-list{-webkit-column-count:2;-moz-column-count:2;column-count:2}}@media screen and (max-width:544px){#ap-list{-webkit-column-count:1;-moz-column-count:1;column-count:1}}#ap-loader{background:rgba(255,255,255,.1);border-radius:5px;padding:.3819820591rem;margin-bottom:.3819820591rem}#ap-box{padding-bottom:.3819820591rem}#psk-modal form{display:flex;align-items:center;margin:.3819820591rem}#psk-modal form>*{margin-left:.3819820591rem;margin-right:.3819820591rem}#psk-modal form>:first-child{margin-left:0}#psk-modal form>:last-child{margin-right:0}#psk-modal form input[type=password]{min-width:5rem}.AP{-webkit-column-break-inside:avoid;page-break-inside:avoid;break-inside:avoid-column;max-width:500px;padding:.2360828548rem}.AP.selected .inner{background:#43de81!important;cursor:default;top:0!important}.AP .inner{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;border-radius:3px;color:#222;background:#afafaf;transition:background-color .5s;display:flex}.AP .inner:active{left:0;top:1px}.AP .inner:hover{background:white}.AP .inner>*{padding:.6180469716rem;white-space:nowrap;word-wrap:normal}.AP .inner .rssi{min-width:2rem;flex:0 0 15%;text-align:right}.AP .inner .rssi:after{padding-left:.090179415rem;content:'%';font-size:.8888888889em}.AP .inner .essid{flex:1 1 70%;min-width:0;text-overflow:ellipsis;overflow:hidden;font-weight:700}.AP .inner .auth{flex:0 0 15%}.page-home #staRSSIperc:after{padding-left:.1459102934rem;content:'%';font-size:.8888888889em}.page-home #staRSSI:after{padding-left:.1459102934rem;content:'dBm';font-size:.8888888889em}#samp-ctrl{display:flex;padding:.3819820591rem;flex-direction:row;justify-content:center;align-items:stretch}@media screen and (max-width:544px){#samp-ctrl{flex-direction:column}}#samp-ctrl>div{margin:.3819820591rem .6180469716rem}#samp-ctrl label{line-height:1.8;font-weight:700}#samp-ctrl input,#samp-ctrl select{width:6em}@media screen and (max-width:544px){#samp-ctrl input,#samp-ctrl select{width:100%}}#samp-ctrl #tile-cfg input{width:3em}#samp-ctrl #interval{width:4.5em}.Box.chartbox{display:flex;flex-direction:row}@media screen and (max-width:544px){.Box.chartbox{flex-direction:column}}.Box.chartbox .stats{flex:0 1;position:relative;padding-bottom:50px}@media screen and (max-width:544px){.Box.chartbox .stats table{margin:0 auto}.Box.chartbox .stats td,.Box.chartbox .stats th{width:50%}}.Box.chartbox .stats td,.Box.chartbox .stats th{white-space:nowrap;word-wrap:normal}.Box.chartbox .stats th sub{font-weight:400}.Box.chartbox .stats td{min-width:100px}.Box.chartbox .stats td:after{font-size:90%;padding-left:.5em}.Box.chartbox .stats #stat-f-s:after{content:"Hz"}.Box.chartbox .stats #stat-i-peak:after,.Box.chartbox .stats #stat-i-rms:after{content:"mA"}.Box.chartbox .stats .ar{position:absolute;bottom:.3819820591rem;width:100%;text-align:center}.Box.chartbox .stats .ar input[type=number]{width:4em}.Box.chartbox .stats .ar input[type=button]{margin-left:.3819820591rem}.page-about .Box{padding-left:1rem;padding-right:1rem}.page-about .Box a{font-weight:700}.page-about #logo{float:right;height:130px}.page-about #logo2{max-width:150px}@media screen and (min-width:545px){.mq-phone{display:none}}@media screen and (max-width:544px){.mq-tablet-min{display:none}}@media screen and (min-width:1001px){.mq-tablet-max{display:none}}@media screen and (max-width:1000px){.mq-normal-min{display:none}} \ No newline at end of file +*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}figure,nav{display:block}canvas,progress{display:inline-block;vertical-align:baseline}[hidden]{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b{font-weight:700}h1,h2{font-size:2em;margin:.67em 0}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,pre{font-family:monospace;font-size:1em}button,input,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}legend{border:0;padding:0}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}.center{text-align:center}.invis{visibility:hidden!important}.hidden{display:none!important}.nb{font-weight:400}html{font-family:Arial,sans-serif;color:#D0D0D0;background:#131315}body,html{border:0 none;margin:0;padding:0;text-decoration:none;width:100%;height:100%;overflow:hidden}a,a:link,a:visited{cursor:pointer;color:#5abfff;text-decoration:none}a:hover{color:#5abfff;text-decoration:underline}.chartexport a{background:#3b7299;border-radius:3px;padding:5px;color:#0c171e;text-decoration:none}.chartexport a:hover{background:#4ea6dd}.chartexport a:active{position:relative;top:1px}.chartexport textarea{margin-top:10px;width:100%;height:10em;resize:vertical}#outer{display:flex;position:absolute;width:100%;height:100%;left:0;right:0;top:0;bottom:0;overflow:hidden;flex-direction:row}@media screen and (max-width:544px){#outer{display:block;overflow-y:scroll}}#menu{flex:0 0 15rem;background:#2c6cab}#menu>*{display:block;text-decoration:none;padding:.6180469716rem 1rem;white-space:nowrap;word-wrap:normal;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#menu #brand{color:white;background:#225282;font-size:120%;text-align:center;position:relative;margin-bottom:1rem}@media screen and (max-width:544px){#menu #brand{background:#2c6cab;cursor:pointer}#menu #brand:after{position:absolute;color:rgba(0,0,0,.2);right:1rem;content:'>';top:50%;font-size:120%;font-weight:700;transform:translateY(-50%) rotate(90deg)}}#menu.expanded #brand{background:#225282}@media screen and (max-width:544px){#menu.expanded #brand:after{transform:translateY(-50%) rotate(-90deg)}}#menu a{font-size:130%;color:white;transition:background-color .2s;text-shadow:0 0 5px rgba(0,0,0,.4)}#menu a.selected,#menu a:hover{background:#1c79d6;text-shadow:0 0 5px rgba(0,0,0,.6)}#menu a.selected{position:relative;box-shadow:0 0 5px rgba(0,0,0,.5)}#menu a:before{content:"▸";padding-right:.5rem;position:relative;top:-.1rem}@media screen and (max-width:544px){#menu a{display:none}}#menu.expanded a{display:block}@media screen and (min-width:545px) and (max-width:1000px){#menu{flex-basis:10rem}#menu #brand{font-size:95%;margin-bottom:.6180469716rem}#menu a{font-size:105%}#menu>*{padding:.3819820591rem .6180469716rem}}#content{flex-grow:1;position:relative;padding:1rem;overflow-y:auto}@media screen and (max-width:544px){#content{padding:.6180469716rem}}#content>*{margin-left:auto;margin-right:auto}#content h1{text-align:center;font-size:2.2806973457em;margin-top:0;margin-bottom:1rem}#content h2{font-size:1.423828125em;margin-bottom:.6180469716rem}#content td,#content th{padding:.3819820591rem}#content tbody th{text-align:right;width:130px;color:#fff}#loader{position:absolute;right:1.618rem;top:1.618rem;transition:opacity .2s;opacity:0}@media screen and (max-width:544px){#loader{top:1rem;right:1rem}}#loader.show{opacity:1}.Box{display:block;max-width:900px;margin-top:1rem;padding:.6180469716rem 1rem;border-radius:3px;background-color:rgba(255,255,255,.07)}@media screen and (max-width:544px){.Box{margin-top:.6180469716rem}}.Box h2,h1+.Box{margin-top:0}.Box.wide{width:initial;max-width:initial}.Box.medium{max-width:1200px}.Box .Valfield{display:inline-block;min-width:10em}.Modal{position:fixed;width:100%;height:100%;left:0;top:0;right:0;bottom:0;display:flex;justify-content:center;align-items:center;transition:opacity .5s;background:rgba(0,0,0,.65);opacity:0}.Modal.visible{opacity:1}.Modal.hidden{display:none}.Dialog{margin:.6180469716rem;padding:1rem;overflow:hidden;max-width:100%;max-height:100%;flex:0 1 30rem;background:#1c1c1e;border-left:6px solid #214e7a;border-right:6px solid #214e7a;box-shadow:0 0 2px 0 #434349,0 0 6px 0 black;border-radius:6px}.Dialog h1,.Dialog h2{margin-top:0}.Dialog p:last-child{margin-bottom:0}.NotifyMsg{position:fixed;bottom:2.617924rem;padding:.6180469716rem 1rem;left:50%;transform:translate(-50%);-webkit-font-smoothing:subpixel-antialiased;-webkit-transform:translateZ(0) scale(1);background:#37a349;color:white;text-shadow:0 0 2px black;box-shadow:0 0 6px 0 rgba(0,0,0,.6);border-radius:5px;max-width:80%;transition:opacity .5s;opacity:0}.NotifyMsg.error{background:#d03e42}@media screen and (max-width:544px){.NotifyMsg{width:calc(100% - 1rem)}}.NotifyMsg.visible{opacity:1}.NotifyMsg.hidden{display:none}.button,button,input[type=button],input[type=reset],input[type=submit]{text-align:center;cursor:pointer;display:inline-block;border-radius:2px;padding:0 .6em;border:0 none;outline:0 none!important;line-height:1.8em;font-size:1.1em;margin-bottom:3px;min-width:5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-shadow:1.5px 1.5px 2px rgba(0,0,0,.8)}.button:active,button:active,input[type=button]:active,input[type=reset]:active,input[type=submit]:active{position:relative;top:2px}.button.narrow,button.narrow,input[type=button].narrow,input[type=reset].narrow,input[type=submit].narrow{min-width:initial}.btn-green,input[type=submit]{background-color:#2ca94b;box-shadow:0 3px 0 #1d7032;text-decoration:none!important}.btn-green,.btn-green:link,.btn-green:visited,input[type=submit],input[type=submit]:link,input[type=submit]:visited{color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:active,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:active,input[type=submit]:hover{background-color:#28ba5c;color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:hover{box-shadow:0 3px 0 #1a773b}.btn-green:active,input[type=submit]:active{box-shadow:0 1px 0 #1a773b}.btn-red,input[type=reset]{background-color:#D04E51;box-shadow:0 3px 0 #aa2d30;text-decoration:none!important}.btn-red,.btn-red:link,.btn-red:visited,input[type=reset],input[type=reset]:link,input[type=reset]:visited{color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:active,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:active,input[type=reset]:hover{background-color:#d4403f;color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:hover{box-shadow:0 3px 0 #9e2423}.btn-red:active,input[type=reset]:active{box-shadow:0 1px 0 #9e2423}.btn-blue{background-color:#3983cd;box-shadow:0 3px 0 #265f98;text-decoration:none!important}.btn-blue,.btn-blue:link,.btn-blue:visited{color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:active,.btn-blue:hover{background-color:#2076C6;color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:hover{box-shadow:0 3px 0 #154c80}.btn-blue:active{box-shadow:0 1px 0 #154c80}input[type=number],input[type=password],input[type=text],select,textarea{border:0 none;border-bottom:2px solid #214e7a;background-color:#303030;color:#fff;padding:6px;line-height:1em;outline:0 none!important;-moz-outline:0 none!important;font-weight:400}input[type=number]:focus,input[type=number]:hover,input[type=password]:focus,input[type=password]:hover,input[type=text]:focus,input[type=text]:hover,select:focus,select:hover,textarea:focus,textarea:hover{border-bottom-color:#2972ba}input[type=number],input[type=password],input[type=text],textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;cursor:text}textarea{font-family:monospace;line-height:1.2em;display:block}form{border:0 none;margin:0;padding:0;text-decoration:none}input[type=number],input[type=password],input[type=text],label.select-wrap,select,textarea{width:250px}form .Row{vertical-align:middle;margin:14px auto;text-align:left;display:flex;flex-direction:row}form .Row:first-child{margin-top:0}form .Row:last-child{margin-bottom:0}form .Row .spacer{width:130px}@media screen and (max-width:544px){form .Row .spacer{display:none}}form .Row.buttons .button,form .Row.buttons input{margin-right:.6180469716rem}form .Row.centered{justify-content:center}form .Row.message{font-size:1em;text-shadow:1px 1px 3px black;text-align:center}form .Row.message.error{color:crimson}form .Row.message.ok{color:#0fe851}form .Row.separator{padding-top:14px;border-top:2px solid rgba(255,255,255,.1)}form .Row textarea{display:inline-block;vertical-align:top;min-height:10rem;flex-grow:1;resize:vertical}form .Row label{font-weight:700;color:#fff;text-shadow:1px 1px 3px black;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}form .Row .checkbox-wrap,form .Row label{display:inline-block;width:130px;text-align:right;padding:8px;align-self:flex-start}form .Row .checkbox-wrap input[type=checkbox]{margin:auto;width:auto;height:auto}form .Row .checkbox-wrap+label{width:250px;padding-left:0;text-align:left;cursor:pointer}@media screen and (max-width:544px){form .Row{flex-direction:column}form .Row.buttons,form .Row.centered{flex-direction:row}form .Row.buttons{justify-content:center}form .Row.buttons :last-child{margin-right:0}form .Row label{padding-left:0;text-align:left;width:auto}form .Row .checkbox-wrap{order:1;text-align:left;padding-bottom:0;border-radius:.4px;width:auto}form .Row .checkbox-wrap+label{width:auto}form .Row input[type=number],form .Row input[type=password],form .Row input[type=text],form .Row textarea{width:100%}}form span.required{color:red}.RadioGroup{display:inline-block;line-height:1.5em;vertical-align:middle}.RadioGroup label{width:auto;text-align:left;cursor:pointer;font-weight:400}.RadioGroup input[type=radio]{vertical-align:middle;margin:0 0 0 5px}@media screen and (-webkit-min-device-pixel-ratio:0){select{padding-right:18px}}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;line-height:1.2em;padding-right:1em}select:-moz-focusring{color:transparent;text-shadow:0 0 0 #fff}select option{background:#303030}label.select-wrap{position:relative;display:inline!important;margin:0!important;padding:0!important;width:auto!important}label.select-wrap:after{content:'<>';font-family:Consolas,monospace;font-weight:700;color:#2972ba;top:50%;transform:translateY(-50%) rotate(90deg);right:2px;position:absolute;z-index:100;pointer-events:none}#ap-list{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:0;-moz-column-gap:0;column-gap:0;margin:0 -.2360828548rem}@media screen and (min-width:545px) and (max-width:1000px){#ap-list{-webkit-column-count:2;-moz-column-count:2;column-count:2}}@media screen and (max-width:544px){#ap-list{-webkit-column-count:1;-moz-column-count:1;column-count:1}}#ap-loader{background:rgba(255,255,255,.1);border-radius:5px;padding:.3819820591rem;margin-bottom:.3819820591rem}#ap-box{padding-bottom:.3819820591rem}#psk-modal form{display:flex;align-items:center;margin:.3819820591rem}#psk-modal form>*{margin-left:.3819820591rem;margin-right:.3819820591rem}#psk-modal form>:first-child{margin-left:0}#psk-modal form>:last-child{margin-right:0}#psk-modal form input[type=password]{min-width:5rem}.AP{-webkit-column-break-inside:avoid;page-break-inside:avoid;break-inside:avoid-column;max-width:500px;padding:.2360828548rem}.AP.selected .inner{background:#43de81!important;cursor:default;top:0!important}.AP .inner{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;border-radius:3px;color:#222;background:#afafaf;transition:background-color .5s;display:flex}.AP .inner:active{left:0;top:1px}.AP .inner:hover{background:white}.AP .inner>*{padding:.6180469716rem;white-space:nowrap;word-wrap:normal}.AP .inner .rssi{min-width:2rem;flex:0 0 15%;text-align:right}.AP .inner .rssi:after{padding-left:.090179415rem;content:'%';font-size:.8888888889em}.AP .inner .essid{flex:1 1 70%;min-width:0;text-overflow:ellipsis;overflow:hidden;font-weight:700}.AP .inner .auth{flex:0 0 15%}.page-about .Box{padding-left:1rem;padding-right:1rem}.page-about .Box a{font-weight:700}.page-about #logo{float:right;height:130px}.page-about #logo2{max-width:150px}@media screen and (min-width:545px){.mq-phone{display:none}}@media screen and (max-width:544px){.mq-tablet-min{display:none}}@media screen and (min-width:1001px){.mq-tablet-max{display:none}}@media screen and (max-width:1000px){.mq-normal-min{display:none}} \ No newline at end of file diff --git a/html/js/all.js b/html/js/all.js index 320e41c..2fff11b 100644 --- a/html/js/all.js +++ b/html/js/all.js @@ -1,3 +1 @@ -function bool(t){return 1===t||"1"===t||t===!0||"true"===t}function numfmt(t,e){var n=Math.pow(10,e);return Math.round(t*n)/n}function estimateLoadTime(t,e){return 1e3/t*e+1500}function msNow(){return+new Date}function msElapsed(t){return msNow()-t}function copyToClipboard(t){if(!document.execCommand)return!1;var e="_hiddenCopyText_";if(n=document.getElementById(e),!n){var n=document.createElement("textarea");n.style.position="absolute",n.style.left="-9999px",n.style.top="0",n.id=e,document.body.appendChild(n)}n.textContent=t;var r=document.activeElement;n.focus(),n.setSelectionRange(0,n.value.length);var i;try{i=document.execCommand("copy")}catch(a){i=!1}return r&&"function"==typeof r.focus&&r.focus(),n.textContent="",i}function errorMsg(t,e){$("#notif").addClass("error"),notify.show(t,e||3e3)}function infoMsg(t,e){$("#notif").removeClass("error"),notify.show(t,e||3e3)}!function(){"use strict";function t(){var t;for(p=!0,t=0;t=0;n-=1)t(e[n])}function r(t){return t.replace(/-\w/g,function(t){return t.charAt(1).toUpperCase()})}function i(t,e){return t.currentStyle?t.currentStyle[r(e)]:g.getComputedStyle?g.getComputedStyle(t,null).getPropertyValue(e):null}function a(t,e){return encodeURIComponent(t).replace(/%20/g,"+")+"="+encodeURIComponent(e).replace(/%20/g,"+")}function o(t,e,n){try{t.style[r(e)]=n}catch(i){}}function s(t){t.style.display="","none"===i(t,"display")&&(t.style.display="block")}function u(t){var e,r,i,o="";if(t.constructor===Object){for(e in t)if(t.hasOwnProperty(e))if(t[e].constructor===Array)for(r=0;r0&&(o+="&"+a(e.name,e.value));break;case"select-multiple":for(i=0;i0?o.substring(1):""}function c(t,e,r){var i,a,o,s=!1;return t&&(i=t.split(/\s+/),n(function(t){for(o=0;o0?y[0].className.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"").replace(/\s+/," "):void 0},e.setClass=function(t){return(t||""===t)&&n(function(e){e.className=t},y),e},e.addClass=function(t){return t&&n(function(e){e.className+=" "+t},y),e},e.removeClass=function(t){return c(t,"remove",y),e},e.toggleClass=function(t){return c(t,"toggle",y),e},e.hasClass=function(t){return c(t,"has",y)},e.html=function(t){return t||""===t?(n(function(e){e.innerHTML=t},y),e):y[0]?y[0].innerHTML:void 0},e.htmlBefore=function(t){return l(t,"before",y),e},e.htmlAfter=function(t){return l(t,"after",y),e},e.htmlAppend=function(t){return l(t,"append",y),e},e.htmlPrepend=function(t){return l(t,"prepend",y),e},e.attr=function(t,r){if(t){if(t=t.toLowerCase(),"undefined"!=typeof r)return n(function(e){"style"===t?e.style.cssText=r:"class"===t?e.className=r:e.setAttribute(t,r)},y),e;if(y[0])if("style"===t){if(y[0].style.cssText)return y[0].style.cssText}else if("class"===t){if(y[0].className)return y[0].className}else if(y[0].getAttribute(t))return y[0].getAttribute(t)}},e.data=function(t,n){return t?e.attr("data-"+t,n):void 0},e.val=function(t){var r,i,a;if(!_.isUndefined(t))return n(function(e){switch(e.nodeName){case"SELECT":for(("string"==typeof t||"number"==typeof t)&&(t=[t]),i=0;i1?r:r[0];case"INPUT":case"TEXTAREA":case"BUTTON":return y[0].value}},e.checked=function(t){return"boolean"==typeof t?(n(function(e){"INPUT"!==e.nodeName||"checkbox"!==e.type&&"radio"!==e.type||(e.checked=t)},y),e):!y[0]||"INPUT"!==y[0].nodeName||"checkbox"!==y[0].type&&"radio"!==y[0].type?void 0:!!y[0].checked},e.on=function(r,i){return(t===g||t===v)&&(y=[t]),n(function(t){v.addEventListener?t.addEventListener(r,i,!1):v.attachEvent&&(t[r+i]=function(){return i.apply(t,arguments)},t.attachEvent("on"+r,t[r+i]))},y),e},e.off=function(r,i){return(t===g||t===v)&&(y=[t]),n(function(t){v.addEventListener?t.removeEventListener(r,i,!1):v.attachEvent&&(t.detachEvent("on"+r,t[r+i]),t[r+i]=null)},y),e},e.ajax=function(t,e,n,r){var i,a,o=u(y),s=e?e.toUpperCase():"GET";_.isNumber(r)&&(r={timeout:r});var c=Chartist.extend({},{nocache:!0,timeout:5e3,loader:!0},r);if(o&&"GET"===s&&(t+=-1===t.indexOf("?")?"?"+o:"&"+o,o=null),i=new XMLHttpRequest){if(c.nocache){var l=(+new Date).toString(36);t+=(-1===t.indexOf("?")?"?":"&")+"_="+l}c.loader&&$("#loader").addClass("show"),i.open(s,t,!0),i.timeout=c.timeout,a=setTimeout(function(){errorMsg("XHR timed out."),i.abort(),c.loader&&$("#loader").removeClass("show")},c.timeout+10),i.onreadystatechange=function(){4===i.readyState&&(c.loader&&$("#loader").removeClass("show"),n&&0!=i.status&&n(i.responseText,i.status),clearTimeout(a))},i.setRequestHeader("X-Requested-With","XMLHttpRequest"),"POST"===s&&i.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),i.send(o)}return i},e.get=function(t,n,r){return e.ajax(t,"get",n,r)},e.post=function(t,n,r){return e.ajax(t,"post",n,r)},e}var f=[],d=[],p=!1,m=!1,v=document,g=window;v.addEventListener?(v.addEventListener("DOMContentLoaded",t,!1),g.addEventListener("load",e,!1)):v.attachEvent?(v.attachEvent("onreadystatechange",t),g.attachEvent("onload",e)):g.onload=e,g.$=h}(),function(t,e){t.Chartist=e()}(this,function(){var t={version:"0.9.7"};return function(t,e,n){"use strict";n.namespaces={svg:"http://www.w3.org/2000/svg",xmlns:"http://www.w3.org/2000/xmlns/",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",ct:"http://gionkunz.github.com/chartist-js/ct"},n.noop=function(t){return t},n.alphaNumerate=function(t){return String.fromCharCode(97+t%26)},n.extend=function(t){t=t||{};var e=Array.prototype.slice.call(arguments,1);return e.forEach(function(e){for(var r in e)"object"!=typeof e[r]||null===e[r]||e[r]instanceof Array?t[r]=e[r]:t[r]=n.extend({},t[r],e[r])}),t},n.replaceAll=function(t,e,n){return t.replace(new RegExp(e,"g"),n)},n.ensureUnit=function(t,e){return"number"==typeof t&&(t+=e),t},n.quantity=function(t){if("string"==typeof t){var e=/^(\d+)\s*(.*)$/g.exec(t);return{value:+e[1],unit:e[2]||void 0}}return{value:t}},n.querySelector=function(t){return t instanceof Node?t:e.querySelector(t)},n.times=function(t){return Array.apply(null,new Array(t))},n.sum=function(t,e){return t+(e?e:0)},n.mapMultiply=function(t){return function(e){return e*t}},n.mapAdd=function(t){return function(e){return e+t}},n.serialMap=function(t,e){var r=[],i=Math.max.apply(null,t.map(function(t){return t.length}));return n.times(i).forEach(function(n,i){var a=t.map(function(t){return t[i]});r[i]=e.apply(null,a)}),r},n.roundWithPrecision=function(t,e){var r=Math.pow(10,e||n.precision);return Math.round(t*r)/r},n.precision=8,n.serialize=function(t){return null===t||void 0===t?t:("number"==typeof t?t=""+t:"object"==typeof t&&(t=JSON.stringify({data:t})),_.escape(t))},n.deserialize=function(t){if("string"!=typeof t)return t;t=_.unescape(t);try{t=JSON.parse(t),t=void 0!==t.data?t.data:t}catch(e){}return t},n.createSvg=function(t,e,r,i){var a;return e=e||"100%",r=r||"100%",Array.prototype.slice.call(t.querySelectorAll("svg")).filter(function(t){return t.getAttributeNS(n.namespaces.xmlns,"ct")}).forEach(function(e){t.removeChild(e)}),a=new n.Svg("svg").attr({width:e,height:r}).addClass(i).attr({style:"width: "+e+"; height: "+r+";"}),t.appendChild(a._node),a},n.normalizeData=function(t){if(t=t||{series:[],labels:[]},t.series=t.series||[],t.labels=t.labels||[],t.series.length>0&&0===t.labels.length){var e,r=n.getDataArray(t);e=r.every(function(t){return t instanceof Array})?Math.max.apply(null,r.map(function(t){return t.length})):r.length,t.labels=n.times(e).map(function(){return""})}return t},n.reverseData=function(t){t.labels.reverse(),t.series.reverse();for(var e=0;ea.high&&(a.high=n),s&&n0?a.low=0:(a.high=1,a.low=0)),a},n.isNum=function(t){return!isNaN(t)&&isFinite(t)},n.isFalseyButZero=function(t){return!t&&0!==t},n.getNumberOrUndefined=function(t){return isNaN(+t)?void 0:+t},n.getMultiValue=function(t,e){return n.isNum(t)?+t:t?t[e||"y"]||0:0},n.rho=function(t){function e(t,n){return t%n===0?n:e(n,t%n)}function n(t){return t*t+1}if(1===t)return t;var r,i=2,a=2;if(t%2===0)return 2;do i=n(i)%t,a=n(n(a))%t,r=e(Math.abs(i-a),t);while(1===r);return r},n.getBounds=function(t,e,r,i){var a,o,s,u=0,c={high:e.high,low:e.low};c.valueRange=c.high-c.low,c.oom=n.orderOfMagnitude(c.valueRange),c.step=Math.pow(10,c.oom),c.min=Math.floor(c.low/c.step)*c.step,c.max=Math.ceil(c.high/c.step)*c.step,c.range=c.max-c.min,c.numberOfSteps=Math.round(c.range/c.step);var l=n.projectLength(t,c.step,c),h=r>l,f=i?n.rho(c.range):0;if(i&&n.projectLength(t,1,c)>=r)c.step=1;else if(i&&f=r)c.step=f;else for(;;){if(h&&n.projectLength(t,c.step,c)<=r)c.step*=2;else{if(h||!(n.projectLength(t,c.step/2,c)>=r))break;if(c.step/=2,i&&c.step%1!==0){c.step*=2;break}}if(u++>1e3)throw new Error("Exceeded maximum number of iterations while optimizing scale step!")}for(o=c.min,s=c.max;o+c.step<=c.low;)o+=c.step;for(;s-c.step>=c.high;)s-=c.step;for(c.min=o,c.max=s,c.range=c.max-c.min,c.values=[],a=c.min;a<=c.max;a+=c.step)c.values.push(n.roundWithPrecision(a));return c},n.createChartRect=function(t,e,r){var i=!(!e.axisX&&!e.axisY),a=i?e.axisY.offset:0,o=i?e.axisX.offset:0,s=t.width()||n.quantity(e.width).value||0,u=t.height()||n.quantity(e.height).value||0,c=n.normalizePadding(e.chartPadding,r);s=Math.max(s,a+c.left+c.right),u=Math.max(u,o+c.top+c.bottom);var l={padding:c,width:function(){return this.x2-this.x1},height:function(){return this.y1-this.y2}};return i?("start"===e.axisX.position?(l.y2=c.top+o,l.y1=Math.max(u-c.bottom,l.y2+1)):(l.y2=c.top,l.y1=Math.max(u-c.bottom-o,l.y2+1)),"start"===e.axisY.position?(l.x1=c.left+a,l.x2=Math.max(s-c.right,l.x1+1)):(l.x1=c.left,l.x2=Math.max(s-c.right-a,l.x1+1))):(l.x1=c.left,l.x2=Math.max(s-c.right,l.x1+1),l.y2=c.top,l.y1=Math.max(u-c.bottom,l.y2+1)),l},n.createGrid=function(t,e,r,i,a,o,s,u){var c={};c[r.units.pos+"1"]=Math.round(t)+.5,c[r.units.pos+"2"]=Math.round(t)+.5,c[r.counterUnits.pos+"1"]=i,c[r.counterUnits.pos+"2"]=i+a;var l=o.elem("line",c,s.join(" "));u.emit("draw",n.extend({type:"grid",axis:r,index:e,group:o,element:l},c))},n.createLabel=function(t,e,r,i,a,o,s,u,c,l,h){var f,d={};d[a.units.pos]=t+s[a.units.pos],d[a.counterUnits.pos]=s[a.counterUnits.pos],d[a.units.len]=e,d[a.counterUnits.len]=o-10;var p=i[r];if(_.isNumber(p)&&(p=n.roundWithPrecision(p,2)),l){var m=''+p+"";f=u.foreignObject(m,n.extend({style:"overflow: visible;"},d))}else f=u.elem("text",d,c.join(" ")).text(p);h.emit("draw",n.extend({type:"label",axis:a,index:r,group:u,element:f,text:p},d))},n.getSeriesOption=function(t,e,n){if(t.name&&e.series&&e.series[t.name]){var r=e.series[t.name];return r.hasOwnProperty(n)?r[n]:e[n]}return e[n]},n.optionsProvider=function(e,r,i){function a(e){var a=s;if(s=n.extend({},c),r)for(u=0;u=2&&e[a]<=e[a-2]?i=!0:(i&&(r.push({pathCoordinates:[],valueData:[]}),i=!1),r[r.length-1].pathCoordinates.push(e[a],e[a+1]),r[r.length-1].valueData.push(n[a/2]));return r}var r={fillHoles:!1};return t=n.extend({},r,t),function i(t,r){var a=e(t,r);if(a.length){if(a.length>1){var o=[];return a.forEach(function(t){o.push(i(t.pathCoordinates,t.valueData))}),n.Svg.Path.join(o)}if(t=a[0].pathCoordinates,r=a[0].valueData,t.length<=4)return n.Interpolation.none()(t,r);var s,u,c=[],l=[],h=t.length/2,f=[],d=[],p=[],m=[];for(s=0;h>s;s++)c[s]=t[2*s],l[s]=t[2*s+1];for(s=0;h-1>s;s++)p[s]=l[s+1]-l[s],m[s]=c[s+1]-c[s],d[s]=p[s]/m[s];for(f[0]=d[0],f[h-1]=d[h-2],s=1;h-1>s;s++)0===d[s]||0===d[s-1]||d[s-1]>0!=d[s]>0?f[s]=0:(f[s]=3*(m[s-1]+m[s])/((2*m[s]+m[s-1])/d[s-1]+(m[s]+2*m[s-1])/d[s]),isFinite(f[s])||(f[s]=0));for(u=(new n.Svg.Path).move(c[0],l[0],!1,r[0]),s=0;h-1>s;s++)u.curve(c[s]+m[s]/3,l[s]+f[s]*m[s]/3,c[s+1]-m[s]/3,l[s+1]-f[s+1]*m[s]/3,c[s+1],l[s+1],!1,r[s+1]);return u}return n.Interpolation.none()([])}},n.Interpolation.step=function(t){var e={postpone:!0,fillHoles:!1};return t=n.extend({},e,t),function(e,r){for(var i,a,o,s=new n.Svg.Path,u=0;u1}).map(function(t){var e=t.pathElements[0],n=t.pathElements[t.pathElements.length-1];return t.clone(!0).position(0).remove(1).move(e.x,g).line(e.x,e.y).position(t.pathElements.length+1).line(n.x,g)}).forEach(function(n){var s=u.elem("path",{d:n.stringify()},t.classNames.area,!0);this.eventEmitter.emit("draw",{type:"area",values:e.normalized[o],path:n.clone(),series:a,seriesIndex:o,axisX:r,axisY:i,chartRect:c,index:o,group:u,element:s})}.bind(this))}}.bind(this)),this.eventEmitter.emit("created",{bounds:i.bounds,chartRect:c,axisX:r,axisY:i,svg:this.svg,options:t})}function i(t,e,r,i){n.Line["super"].constructor.call(this,t,e,a,n.extend({},a,r),i)}var a={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,type:void 0},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,type:void 0,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,showLine:!0,showPoint:!0,showArea:!1,areaBase:0,lineSmooth:!0,low:void 0,high:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},fullWidth:!1,reverseData:!1,classNames:{chart:"ct-chart-line",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",line:"ct-line",point:"ct-point",area:"ct-area",grid:"ct-grid",gridGroup:"ct-grids",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};n.Line=n.Base.extend({constructor:i,createChart:r})}(window,document,t),function(t,e,n){"use strict";function r(t){this.data=n.normalizeData(this.data);var e,r={raw:this.data,normalized:t.distributeSeries?n.getDataArray(this.data,t.reverseData,t.horizontalBars?"x":"y").map(function(t){return[t]}):n.getDataArray(this.data,t.reverseData,t.horizontalBars?"x":"y")};this.svg=n.createSvg(this.container,t.width,t.height,t.classNames.chart+(t.horizontalBars?" "+t.classNames.horizontalBars:""));var i=this.svg.elem("g").addClass(t.classNames.gridGroup),o=this.svg.elem("g"),s=this.svg.elem("g").addClass(t.classNames.labelGroup);if(t.stackBars&&0!==r.normalized.length){var u=n.serialMap(r.normalized,function(){return Array.prototype.slice.call(arguments).map(function(t){return t}).reduce(function(t,e){return{x:t.x+(e&&e.x)||0,y:t.y+(e&&e.y)||0}},{x:0,y:0})});e=n.getHighLow([u],n.extend({},t,{referenceValue:0}),t.horizontalBars?"x":"y")}else e=n.getHighLow(r.normalized,n.extend({},t,{referenceValue:0}),t.horizontalBars?"x":"y");e.high=+t.high||(0===t.high?0:e.high),e.low=+t.low||(0===t.low?0:e.low);var c,l,h,f,d,p=n.createChartRect(this.svg,t,a.padding);l=t.distributeSeries&&t.stackBars?r.raw.labels.slice(0,1):r.raw.labels,t.horizontalBars?(c=f=void 0===t.axisX.type?new n.AutoScaleAxis(n.Axis.units.x,r,p,n.extend({},t.axisX,{highLow:e,referenceValue:0})):t.axisX.type.call(n,n.Axis.units.x,r,p,n.extend({},t.axisX,{highLow:e,referenceValue:0})),h=d=void 0===t.axisY.type?new n.StepAxis(n.Axis.units.y,r,p,{ticks:l}):t.axisY.type.call(n,n.Axis.units.y,r,p,t.axisY)):(h=f=void 0===t.axisX.type?new n.StepAxis(n.Axis.units.x,r,p,{ticks:l}):t.axisX.type.call(n,n.Axis.units.x,r,p,t.axisX),c=d=void 0===t.axisY.type?new n.AutoScaleAxis(n.Axis.units.y,r,p,n.extend({},t.axisY,{highLow:e,referenceValue:0})):t.axisY.type.call(n,n.Axis.units.y,r,p,n.extend({},t.axisY,{highLow:e,referenceValue:0})));var m=t.horizontalBars?p.x1+c.projectValue(0):p.y1-c.projectValue(0),v=[];h.createGridAndLabels(i,s,this.supportsForeignObject,t,this.eventEmitter),c.createGridAndLabels(i,s,this.supportsForeignObject,t,this.eventEmitter),r.raw.series.forEach(function(e,i){var a,s,u=i-(r.raw.series.length-1)/2;a=t.distributeSeries&&!t.stackBars?h.axisLength/r.normalized.length/2:t.distributeSeries&&t.stackBars?h.axisLength/2:h.axisLength/r.normalized[i].length/2,s=o.elem("g"),s.attr({"ct:series-name":e.name,"ct:meta":n.serialize(e.meta)}),s.addClass([t.classNames.series,e.className||t.classNames.series+"-"+n.alphaNumerate(i)].join(" ")),r.normalized[i].forEach(function(o,l){var g,x,y,b;if(b=t.distributeSeries&&!t.stackBars?i:t.distributeSeries&&t.stackBars?0:l,g=t.horizontalBars?{x:p.x1+c.projectValue(o&&o.x?o.x:0,l,r.normalized[i]),y:p.y1-h.projectValue(o&&o.y?o.y:0,b,r.normalized[i])}:{x:p.x1+h.projectValue(o&&o.x?o.x:0,b,r.normalized[i]),y:p.y1-c.projectValue(o&&o.y?o.y:0,l,r.normalized[i])},h instanceof n.StepAxis&&(h.options.stretch||(g[h.units.pos]+=a*(t.horizontalBars?-1:1)),g[h.units.pos]+=t.stackBars||t.distributeSeries?0:u*t.seriesBarDistance*(t.horizontalBars?-1:1)),y=v[l]||m,v[l]=y-(m-g[h.counterUnits.pos]),void 0!==o){var w={};w[h.units.pos+"1"]=g[h.units.pos],w[h.units.pos+"2"]=g[h.units.pos],!t.stackBars||"accumulate"!==t.stackMode&&t.stackMode?(w[h.counterUnits.pos+"1"]=m,w[h.counterUnits.pos+"2"]=g[h.counterUnits.pos]):(w[h.counterUnits.pos+"1"]=y,w[h.counterUnits.pos+"2"]=v[l]),w.x1=Math.min(Math.max(w.x1,p.x1),p.x2),w.x2=Math.min(Math.max(w.x2,p.x1),p.x2),w.y1=Math.min(Math.max(w.y1,p.y2),p.y1),w.y2=Math.min(Math.max(w.y2,p.y2),p.y1),x=s.elem("line",w,t.classNames.bar).attr({"ct:value":[o.x,o.y].filter(n.isNum).join(","),"ct:meta":n.getMetaData(e,l)}),this.eventEmitter.emit("draw",n.extend({type:"bar",value:o,index:l,meta:n.getMetaData(e,l),series:e,seriesIndex:i,axisX:f,axisY:d,chartRect:p,group:s,element:x},w))}}.bind(this))}.bind(this)),this.eventEmitter.emit("created",{bounds:c.bounds,chartRect:p,axisX:f,axisY:d,svg:this.svg,options:t})}function i(t,e,r,i){n.Bar["super"].constructor.call(this,t,e,a,n.extend({},a,r),i)}var a={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,scaleMinSpace:30,onlyInteger:!1},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,high:void 0,low:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},seriesBarDistance:15,stackBars:!1,stackMode:"accumulate",horizontalBars:!1,distributeSeries:!1,reverseData:!1,classNames:{chart:"ct-chart-bar",horizontalBars:"ct-horizontal-bars",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",bar:"ct-bar",grid:"ct-grid",gridGroup:"ct-grids",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};n.Bar=n.Base.extend({constructor:i,createChart:r})}(window,document,t),t}),function(t,e){t["Chartist.plugins.ctAxisTitle"]=e()}(this,function(){return function(t,e,n){"use strict";var r={axisTitle:"",axisClass:"ct-axis-title",offset:{x:0,y:0},textAnchor:"middle",flipText:!1},i={axisX:r,axisY:r};n.plugins=n.plugins||{},n.plugins.ctAxisTitle=function(t){return t=n.extend({},i,t),function(e){e.on("created",function(e){var r,i,a;if(t.axisX.axisTitle&&e.axisX&&(r=e.axisX.axisLength/2+e.options.axisY.offset+e.options.chartPadding.left,i=e.options.chartPadding.top,"end"===e.options.axisY.position&&(r-=e.options.axisY.offset),"end"===e.options.axisX.position&&(i+=e.axisY.axisLength),a=new n.Svg("text"),a.addClass(t.axisX.axisClass),a.text(t.axisX.axisTitle),a.attr({x:r+t.axisX.offset.x,y:i+t.axisX.offset.y,"text-anchor":t.axisX.textAnchor}),e.svg.append(a,!0)),t.axisY.axisTitle&&e.axisY){r=0,i=e.axisY.axisLength/2+e.options.chartPadding.top,"start"===e.options.axisX.position&&(i+=e.options.axisX.offset),"end"===e.options.axisY.position&&(r=e.axisX.axisLength);var o="rotate("+(t.axisY.flipText?-90:90)+", "+r+", "+i+")";a=new n.Svg("text"),a.addClass(t.axisY.axisClass),a.text(t.axisY.axisTitle),a.attr({x:r+t.axisY.offset.x,y:i+t.axisY.offset.y,transform:o,"text-anchor":t.axisY.textAnchor}),e.svg.append(a,!0)}})}}}(window,document,Chartist),Chartist.plugins.ctAxisTitle}),function(t,e){t["Chartist.plugins.zoom"]=e()}(this,function(){return function(t,e,n){"use strict";function r(t){t.attr({style:"display:none"})}function i(t){t.attr({style:"display:block"})}function a(t,e){var n=t.x,r=t.y,i=e.x-n,a=e.y-r;return 0>i&&(i=-i,n=e.x),0>a&&(a=-a,r=e.y),{x:n,y:r,width:i,height:a}}function o(t,e){return s(t.clientX,t.clientY,e)}function s(t,e,n){var r="svg"===n.tagName?n:n.ownerSVGElement,i=r.getScreenCTM(),a=r.createSVGPoint();return a.x=t,a.y=e,a=a.matrixTransform(i.inverse()),a||{x:0,y:0}}function u(t,e){var n=e.bounds.max,r=e.bounds.min;if(e.scale&&"log"===e.scale.type){var i=e.scale.base;return Math.pow(i,t*c(n/r,i)/e.axisLength)*r}return t*e.bounds.range/e.axisLength+r}function c(t,e){return Math.log(t)/Math.log(e)}var l={};n.plugins=n.plugins||{},n.plugins.zoom=function(t){return t=n.extend({},l,t),function(e){function s(t){var e=o(t,b);return e.id=t.identifier,e}function c(t){for(var e=0;e1&&(y.attr(a(M[0],M[1])),i(y))}function h(t){for(var e=t.changedTouches,n=0;n1&&(y.attr(a(M[0],M[1])),i(y),t.preventDefault())}function f(t){d(t.changedTouches)}function d(t){for(var e=0;e=0&&M.splice(n,1)}}function p(t){M.length>1&&g(a(M[0],M[1])),d(t.changedTouches),r(y)}function m(t){0===t.button&&(A=o(t,b),y.attr(a(A,A)),i(y),t.preventDefault())}function v(e){if(0===e.button){var n=a(A,o(e,b));g(n),A=null,r(y),e.preventDefault()}else t.resetOnRightMouseBtn&&2===e.button&&(O(),e.preventDefault())}function g(t){if(t.width>5&&t.height>5){var n=t.x-S.x1,r=n+t.width,i=S.y1-t.y,a=i-t.height,o=u(n,w),s=u(r,w),c=u(a,E),l=u(i,E),h=e.options.explicitBounds;_.isUndefined(h)||(_.isUndefined(h.xLow)||(o=Math.max(h.xLow,o)),_.isUndefined(h.xHigh)||(s=Math.min(h.xHigh,s)),_.isUndefined(h.yLow)||(c=Math.max(h.yLow,c)),_.isUndefined(h.yHigh)||(l=Math.min(h.yHigh,l))),e.options.axisX.highLow={low:o,high:s},e.options.axisY.highLow={low:c,high:l},e.update(e.data,e.options),C&&C(e,O)}}function x(t){if(A){var e=o(t,b);y.attr(a(A,e)),t.preventDefault()}}if(e instanceof n.Line){var y,b,w,E,S,A,C=t.onZoom,M=[];e.on("draw",function(t){var e=t.type;("line"===e||"bar"===e||"area"===e||"point"===e)&&t.element.attr({"clip-path":"url(#zoom-mask)"})}),e.on("created",function(t){w=t.axisX,E=t.axisY,S=t.chartRect,b=t.svg._node,y=t.svg.elem("rect",{x:10,y:10,width:100,height:100},"ct-zoom-rect"),r(y);var e=t.svg.querySelector("defs")||t.svg.elem("defs"),n=S.width(),i=S.height();e.elem("clipPath",{id:"zoom-mask"}).elem("rect",{x:S.x1,y:S.y2,width:n,height:i,fill:"white"}),b.addEventListener("mousedown",m),b.addEventListener("mouseup",v),b.addEventListener("mousemove",x),b.addEventListener("touchstart",l),b.addEventListener("touchmove",h),b.addEventListener("touchend",p),b.addEventListener("touchcancel",f)});var O=function(){e.options.axisX.highLow=null,e.options.axisY.highLow=null,e.update(e.data,e.options)}}}}}(window,document,Chartist),Chartist.plugins.zoom}),function(){function t(t,e){return t.set(e[0],e[1]),t}function e(t,e){return t.add(e),t}function n(t,e){for(var n=-1,r=t.length;++n-1&&t%1==0&&e>t}function f(t){var e=-1,n=Array(t.size);return t.forEach(function(t,r){n[++e]=[r,t]}),n}function d(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=t}),n}function p(t){return gn[t]}function m(){}function v(){}function g(t,e){return y(t,e)&&delete t[e]}function x(t,e){if(Gn){var n=t[e];return n===ye?ve:n}return Nn.call(t,e)?t[e]:ve}function y(t,e){return Gn?t[e]!==ve:Nn.call(t,e)}function b(t,e,n){t[e]=Gn&&n===ve?ye:n}function w(t){var e=-1,n=t?t.length:0;for(this.clear();++en)return!1;var r=t.length-1;return n==r?t.pop():Xn.call(t,n,1),!0}function T(t,e){var n=P(t,e);return 0>n?ve:t[n][1]}function I(t,e){return P(t,e)>-1}function P(t,e){for(var n=t.length;n--;)if(Yt(t[n][0],e))return n;return-1}function z(t,e,n){var r=P(t,e);0>r?t.push([e,n]):t[r][1]=n}function B(t,e,n){var r=t[e];Nn.call(t,e)&&Yt(r,n)&&(n!==ve||e in t)||(t[e]=n)}function R(t,e){return t&&pt(e,oe(e),t)}function U(t){return"function"==typeof t?t:de}function X(t){return ar(t)?t:Bt(t)}function Y(t,e,r,i,a,o,s){var u;if(i&&(u=o?i(t,a,o,s):i(t)),u!==ve)return u;if(!Gt(t))return t;var c=ar(t);if(c){if(u=Ot(t),!e)return dt(t,u)}else{var h=_t(t),f=h==$e||h==Ne;if(or(t))return ot(t,e);if(h==Te||h==Ce||f&&!o){if(l(t))return o?t:{};if(u=Lt(f?{}:t),!e)return u=R(u,t),r?vt(t,u):u}else{if(!mn[h])return o?t:{};u=$t(t,h,e)}}s||(s=new M);var d=s.get(t);return d?d:(s.set(t,u),(c?n:D)(t,function(n,a){B(u,a,Y(n,e,r,i,a,t,s))}),r&&!c?vt(t,u):u)}function q(t){return Gt(t)?Rn(t):{}}function D(t,e){return t&&nr(t,e,oe)}function F(t,e){e=kt(e,t)?[e+""]:X(e);for(var n=0,r=e.length;null!=t&&r>n;)t=t[e[n++]];return n&&n==r?t:ve}function H(t,e){return Nn.call(t,e)||"object"==typeof t&&e in t&&null===zn(t)}function V(t,e){return e in Object(t)}function G(t,e,n,r,i){return t===e?!0:null==t||null==e||!Gt(t)&&!Wt(e)?t!==t&&e!==e:W(t,e,G,n,r,i)}function W(t,e,n,r,i,a){var o=ar(t),s=ar(e),u=_e,c=_e;o||(u=_t(t),u=u==Ce?Te:u),s||(c=_t(e),c=c==Ce?Te:c);var h=u==Te&&!l(t),f=c==Te&&!l(e),d=u==c;if(d&&!h)return a||(a=new M),o||te(t)?bt(t,e,n,r,i,a):wt(t,e,u,n,r,i,a);if(!(i&we)){var p=h&&Nn.call(t,"__wrapped__"),m=f&&Nn.call(e,"__wrapped__");if(p||m)return a||(a=new M),n(p?t.value():t,m?e.value():e,r,i,a)}return d?(a||(a=new M),Et(t,e,n,r,i,a)):!1}function Q(t,e,n,r){var i=n.length,a=i,o=!r;if(null==t)return!a;for(t=Object(t);i--;){var s=n[i];if(o&&s[2]?s[1]!==t[s[0]]:!(s[0]in t))return!1}for(;++ie&&(e=-e>i?0:i+e),n=n>i?i:n,0>n&&(n+=i),i=e>n?0:n-e>>>0,e>>>=0;for(var a=Array(i);++re?1:-1:ne(r)||0,it(e,n,r,t)}}function bt(t,e,n,r,i,o){var s=-1,u=i&we,c=i&be,l=t.length,h=e.length;if(l!=h&&!(u&&h>l))return!1;var f=o.get(t);if(f)return f==e;var d=!0;for(o.set(t,e);++s-1&&t%1==0&&Se>=t}function Gt(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function Wt(t){return!!t&&"object"==typeof t}function Qt(t){return null==t?!1:Ht(t)?kn.test($n.call(t)):Wt(t)&&(l(t)?kn:hn).test(t)}function Zt(t){return"number"==typeof t||Wt(t)&&jn.call(t)==ke}function Jt(t){return"string"==typeof t||!ar(t)&&Wt(t)&&jn.call(t)==ze}function Kt(t){return"symbol"==typeof t||Wt(t)&&jn.call(t)==Be}function te(t){return Wt(t)&&Vt(t.length)&&!!pn[jn.call(t)]}function ee(t){return t===ve}function ne(t){if(Gt(t)){var e=Ht(t.valueOf)?t.valueOf():t;t=Gt(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(on,"");var n=ln.test(t);return n||fn.test(t)?yn(t.slice(2),n?2:8):cn.test(t)?Ae:+t}function re(t){if("string"==typeof t)return t;if(null==t)return"";if(Kt(t))return tr?tr.call(t):"";var e=t+"";return"0"==e&&1/t==-Ee?"-0":e}function ie(t,e,n){var r=null==t?ve:F(t,e);return r===ve?n:r}function ae(t,e){return Mt(t,e,V)}function oe(t){var e=It(t);if(!e&&!Dt(t))return J(t);var n=Nt(t),r=!!n,i=n||[],a=i.length;for(var o in t)!H(t,o)||r&&("length"==o||h(o,a))||e&&"constructor"==o||i.push(o);return i}function se(t){return s(t,oe(t))}function ue(t){return t=re(t),t&&Ke.test(t)?t.replace(Ze,c):t}function ce(t){return t=re(t),t&&an.test(t)?t.replace(rn,"\\$&"):t}function le(){var t=arguments,e=re(t[0]);return t.length<3?e:e.replace(t[1],t[2])}function he(t){return t=re(t),t&&Je.test(t)?t.replace(Qe,p):t}function fe(t){return function(){return t}}function de(t){return t}function pe(t){return Z("function"==typeof t?t:Y(t,!0))}function me(t){return kt(t)?nt(t):rt(t)}var ve,ge="4.6.1",xe=200,ye="__lodash_hash_undefined__",be=1,we=2,Ee=1/0,Se=9007199254740991,Ae=NaN,Ce="[object Arguments]",_e="[object Array]",Me="[object Boolean]",Oe="[object Date]",Le="[object Error]",$e="[object Function]",Ne="[object GeneratorFunction]",je="[object Map]",ke="[object Number]",Te="[object Object]",Ie="[object RegExp]",Pe="[object Set]",ze="[object String]",Be="[object Symbol]",Re="[object WeakMap]",Ue="[object ArrayBuffer]",Xe="[object Float32Array]",Ye="[object Float64Array]",qe="[object Int8Array]",De="[object Int16Array]",Fe="[object Int32Array]",He="[object Uint8Array]",Ve="[object Uint8ClampedArray]",Ge="[object Uint16Array]",We="[object Uint32Array]",Qe=/&(?:amp|lt|gt|quot|#39|#96);/g,Ze=/[&<>"'`]/g,Je=RegExp(Qe.source),Ke=RegExp(Ze.source),tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,en=/^\w*$/,nn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g,rn=/[\\^$.*+?()[\]{}|]/g,an=RegExp(rn.source),on=/^\s+|\s+$/g,sn=/\\(\\)?/g,un=/\w*$/,cn=/^[-+]0x[0-9a-f]+$/i,ln=/^0b[01]+$/i,hn=/^\[object .+?Constructor\]$/,fn=/^0o[0-7]+$/i,dn=/^(?:0|[1-9]\d*)$/,pn={};pn[Xe]=pn[Ye]=pn[qe]=pn[De]=pn[Fe]=pn[He]=pn[Ve]=pn[Ge]=pn[We]=!0,pn[Ce]=pn[_e]=pn[Ue]=pn[Me]=pn[Oe]=pn[Le]=pn[$e]=pn[je]=pn[ke]=pn[Te]=pn[Ie]=pn[Pe]=pn[ze]=pn[Re]=!1;var mn={};mn[Ce]=mn[_e]=mn[Ue]=mn[Me]=mn[Oe]=mn[Xe]=mn[Ye]=mn[qe]=mn[De]=mn[Fe]=mn[je]=mn[ke]=mn[Te]=mn[Ie]=mn[Pe]=mn[ze]=mn[Be]=mn[He]=mn[Ve]=mn[Ge]=mn[We]=!0,mn[Le]=mn[$e]=mn[Re]=!1;var vn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},gn={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},xn={"function":!0,object:!0},yn=parseInt,bn=xn[typeof exports]&&exports&&!exports.nodeType?exports:ve,wn=xn[typeof module]&&module&&!module.nodeType?module:ve,En=wn&&wn.exports===bn?bn:ve,Sn=u(bn&&wn&&"object"==typeof global&&global),An=u(xn[typeof self]&&self),Cn=u(xn[typeof window]&&window),_n=u(xn[typeof this]&&this),Mn=Sn||Cn!==(_n&&_n.window)&&Cn||An||_n||Function("return this")(),On=Array.prototype,Ln=Object.prototype,$n=Function.prototype.toString,Nn=Ln.hasOwnProperty,jn=Ln.toString,kn=RegExp("^"+$n.call(Nn).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Tn=En?Mn.Buffer:ve,In=Mn.Symbol,Pn=Mn.Uint8Array,zn=Object.getPrototypeOf,Bn=Object.getOwnPropertySymbols,Rn=Object.create,Un=Ln.propertyIsEnumerable,Xn=On.splice,Yn=Math.ceil,qn=Object.keys,Dn=Math.max,Fn=Ct(Mn,"Map"),Hn=Ct(Mn,"Set"),Vn=Ct(Mn,"WeakMap"),Gn=Ct(Object,"create"),Wn=Fn?$n.call(Fn):"",Qn=Hn?$n.call(Hn):"",Zn=Vn?$n.call(Vn):"",Jn=In?In.prototype:ve,Kn=Jn?Jn.valueOf:ve,tr=Jn?Jn.toString:ve,er=gt(D),nr=xt(),rr=nt("length"),ir=Bn||function(){return[]};(Fn&&_t(new Fn)!=je||Hn&&_t(new Hn)!=Pe||Vn&&_t(new Vn)!=Re)&&(_t=function(t){var e=jn.call(t),n=e==Te?t.constructor:null,r="function"==typeof n?$n.call(n):"";if(r)switch(r){case Wn:return je;case Qn:return Pe;case Zn:return Re}return e});var ar=Array.isArray,or=Tn?function(t){return t instanceof Tn}:fe(!1),sr=yt();v.prototype=Gn?Gn(null):Ln,w.prototype.clear=E,w.prototype["delete"]=S,w.prototype.get=A,w.prototype.has=C,w.prototype.set=_,M.prototype.clear=O,M.prototype["delete"]=L,M.prototype.get=$,M.prototype.has=N,M.prototype.set=j,m.constant=fe,m.iteratee=pe,m.keys=oe,m.map=Xt,m.property=me,m.range=sr,m.toPairs=se,m.eq=Yt,m.escape=ue,m.escapeRegExp=ce,m.forEach=Ut,m.get=ie,m.hasIn=ae,m.identity=de,m.isArguments=qt,m.isArray=ar,m.isArrayLike=Dt,m.isArrayLikeObject=Ft,m.isBuffer=or,m.isFunction=Ht,m.isLength=Vt,m.isNative=Qt,m.isNumber=Zt,m.isObject=Gt,m.isObjectLike=Wt,m.isString=Jt,m.isSymbol=Kt,m.isTypedArray=te,m.isUndefined=ee,m.last=Rt,m.replace=le,m.toNumber=ne,m.toString=re,m.unescape=he,m.each=Ut,m.VERSION=ge,(Cn||An||{})._=m,Mn._=m}.call(this),Math.log10=Math.log10||function(t){return Math.log(t)/Math.LN10},String.prototype.format=function(){var t=this,e=arguments;1==arguments.length&&(_.isArray(arguments[0])||_.isObject(arguments[0]))&&(e=arguments[0]);for(var n in e)if(e.hasOwnProperty(n)){var r=n;n.match(/^\{.*\}$/)||(n="{"+n+"}");var i=new RegExp(_.escapeRegExp(n),"g");t=t.replace(i,e[r])}return t};var modal=function(){var t={};return t.show=function(t){var e=$(t);e.removeClass("hidden visible"),setTimeout(function(){e.addClass("visible")},1)},t.hide=function(t){var e=$(t);e.removeClass("visible"),setTimeout(function(){e.addClass("hidden")},500)},t.init=function(){$(".Modal").on("click",function(){$(this).hasClass("no-close")||t.hide(this)}),$(".Dialog").on("click",function(t){t.stopImmediatePropagation()}),$(window).on("keydown",function(e){27==e.which&&t.hide(".Modal")})},t}(),notify=function(){var t,e,n={},r="#notif";return n.show=function(i,a){$(r).html(i),modal.show(r),clearTimeout(t),clearTimeout(e),_.isUndefined(a)||(t=setTimeout(n.hide,a))},n.hide=function(){var t=$(r);t.removeClass("visible"),e=setTimeout(function(){t.addClass("hidden")},250)},n.init=function(){$(r).on("click",function(){n.hide(this)})},n}();$().ready(function(){setInterval(function(){$(".anim-dots").each(function(t){var e=$(t),n=e.html()+".";5==n.length&&(n="."),e.html(n)})},1e3),$("input[type=number]").on("mousewheel",function(t){var e=+$(this).val(),n=+($(this).attr("step")||1),r=$(this).attr("min"),i=$(this).attr("max");if(t.wheelDelta>0?e+=n:e-=n,_.isUndefined(r)||(e=Math.max(e,r)),_.isUndefined(i)||(e=Math.min(e,i)),$(this).val(e),"createEvent"in document){var a=document.createEvent("HTMLEvents");a.initEvent("change",!1,!0),$(this)[0].dispatchEvent(a)}else $(this)[0].fireEvent("onchange");t.preventDefault()}),modal.init(),notify.init()});var page_wifi=function(){function t(t,e){if(200!=e)return void n(5e3);t=JSON.parse(t);var a=!bool(t.result.inProgress)&&t.result.APs.length>0;if(n(a?15e3:1e3),a){var o=$("#ap-list");$(".AP").remove(),o.toggle(a),$("#ap-loader").toggle(!a),t.result.APs.sort(function(t,e){return e.rssi-t.rssi}).forEach(function(t){if(t.enc=parseInt(t.enc),!(t.enc>4)){var e=document.createElement("div"),n=$(e).data("ssid",t.essid).data("pwd",0!=t.enc).addClass("AP");t.essid==r.current&&n.addClass("selected");var a=document.createElement("div");$(a).addClass("inner").htmlAppend('
{0}
'.format(t.rssi_perc)).htmlAppend('
{0}
'.format(_.escape(t.essid))).htmlAppend('
{0}
'.format(i[t.enc]));n.on("click",function(){var t=$(this);$("#conn-essid").val(t.data("ssid")),$("#conn-passwd").val(""),t.data("pwd")?modal.show("#psk-modal"):$("#conn-form").submit()}),e.appendChild(a), -o[0].appendChild(e)}})}}function e(){$().get(_root+"/wifi/scan",t)}function n(t){setTimeout(e,t)}var r={},i=["Open","WEP","WPA","WPA2","WPA/WPA2"];return r.init=function(){e()},r}(),page_waveform=function(){function t(t){var e,n,r=window.matchMedia("screen and (min-width: 544px)"),i=!r.matches,o="FFT"==t.stats.format;o?(e="Frequency - [ Hz ]",n="Magnitude - [ mA ]"):(e="Sample time - [ ms ]",n="Current - [ mA ]");var s=Math.max(-t.stats.min,t.stats.max),l=Math.max(s,10);$("#stat-count").html(t.stats.count),$("#stat-f-s").html(numfmt(t.stats.freq,2)),$("#stat-i-peak").html(numfmt(s,2)),$("#stat-i-rms").html(numfmt(t.stats.rms,2)),$(".stats").removeClass("invis");var h=o?t.stats.freq/t.stats.count:1e3/t.stats.freq,f=_.map(t.samples,function(t,e){return{x:e*h,y:t}}),d=[Chartist.plugins.zoom({resetOnRightMouseBtn:!0,onZoom:function(t,e){a=e,u=t.options.axisX.highLow,c=t.options.axisY.highLow}})];i||d.push(Chartist.plugins.ctAxisTitle({axisX:{axisTitle:e,offset:{x:0,y:55}},axisY:{axisTitle:n,flipText:!0,offset:{x:0,y:15}}}));var p,m,v,g;u?(p=u.high,m=u.low,v=c.high,g=c.low):(v=o?void 0:l,g=o?0:-l),new Chartist.Line("#chart",{series:[{name:"a",data:f}]},{showPoint:!1,showArea:o,fullWidth:!0,chartPadding:i?{right:20,bottom:5,left:0}:{right:25,bottom:30,left:25},series:{a:{lineSmooth:Chartist.Interpolation.monotoneCubic()}},axisX:{type:Chartist.AutoScaleAxis,high:p,low:m},axisY:{type:Chartist.AutoScaleAxis,high:v,low:g},explicitBounds:{xLow:0,yLow:o?0:void 0,xHigh:f[f.length-1].x},plugins:d})}function e(e,n){if(f=!1,200!=n)errorMsg("Request failed.",1e3);else{var i=JSON.parse(e);i.success?($(".chartexport").removeClass("hidden"),v=i,t(i)):errorMsg("Sampling failed.",1e3)}d&&(m=setTimeout(r,Math.max(0,p-msElapsed(s))))}function n(){g.count=$("#count").val(),g.freq=$("#freq").val()*("fft"==o?2:1)}function r(){f&&(errorMsg("Request already pending - aborting."),l.abort()),f=!0,s=msNow();var t=g.count,n=g.freq,r=_root+"/measure/"+o+"?n="+t+"&fs="+n;return l=$().get(r,e,estimateLoadTime(n,t)),!0}function i(){p=+$("#ar-time").val(),n(),d=!d,d?r():clearTimeout(m),$("#ar-btn").toggleClass("btn-blue").toggleClass("btn-red").val(d?"Stop":"Auto")}var a,o,s,u,c,l,h={},f=!1,d=!1,p=1,m=-1,v=null,g={count:0,freq:0};return h.init=function(t){function e(){n(),r()}o=t,$("#load").on("click",e),$(".chartexport a").on("click",function(){var t=$(this).data("sep"),e="",n="fft"==o,r=n?v.stats.freq/v.stats.count:1e3/v.stats.freq,i=n?3:2;switch(t){case"space":e=v.samples.join(" ");break;case"comma":e=v.samples.join(",");break;case"newline":e=v.samples.join("\n");break;case"csv":e=_.map(v.samples,function(t,e){return numfmt(e*r,i)+","+t}).join("\n")}if(copyToClipboard(e))infoMsg("Copy success!");else{var a=$("#copybox");a.removeClass("hidden"),a.val(e)}}),$("#count,#freq").on("keyup",function(t){13==t.which&&e()}),$("#chart").on("contextmenu",function(t){return a&&a(),a=null,u=null,c=null,t.preventDefault(),!1}),$("#ar-btn").on("click",i)},h}(),page_spectrogram=function(){function t(t){var e,n,r,i;t=Math.log10(1+t),t>2&&(t=2),0>t&&(t=0);for(var a=0;a=s&&(e=s,r=o),s>=t){n=s,i=o;break}}var u=(t-e)/(n-e);e==n&&(u=0);var c=Math.round(r[1]+(i[1]-r[1])*u),l=Math.round(r[2]+(i[2]-r[2])*u),h=Math.round(r[3]+(i[3]-r[3])*u);return"rgb("+c+","+l+","+h+")"}function e(){var t=c.getImageData(g.x+g.dx,g.y,g.w-g.dx,g.h+10);c.fillStyle="black",c.fillRect(g.x,g.y,g.w,g.h),c.clearRect(g.x,g.y+g.h+1,g.w,10),c.putImageData(t,g.x,g.y)}function n(n){e();for(var r=x.sampCount/2,i=0;r>i;i++){var a;if(i*g.dy>g.h)break;a=i>n.length?"#000":t(n[i]),c.fillStyle=a;var o=g.x+g.w-g.dx,s=g.y+g.h-(i+1)*g.dy,u=g.dx,l=g.dy;s=950){p=msNow();var h=!1;msElapsed(m)>9500&&(h=!0,m=msNow()),c.strokeStyle="white",c.beginPath(),c.moveTo(g.x+g.w-.5,g.y+g.h+1),c.lineTo(g.x+g.w-.5,g.y+g.h+1+(h?6:2)),c.stroke()}}function r(t,e){if(h=!1,200==e)try{var r=JSON.parse(t);r.success?n(r.samples):errorMsg("Sampling failed.",1e3)}catch(a){errorMsg(a)}else errorMsg("Request failed.",1e3);y&&(l=setTimeout(i,Math.max(0,x.interval-msElapsed(d))))}function i(){h&&(errorMsg("Request already pending - aborting."),f.abort()),h=!0,d=msNow();var t=x.freq,e=x.sampCount,n=_root+"/measure/fft?n="+e+"&fs="+t;return f=$().get(n,r,estimateLoadTime(t,e)),!0}function a(){for(var e=8,n=10,r=g.h-12,i=g.y+6,a=g.x-e-n,o=100/r,s=0;r>s;s++){var u=t(s*o),l=t((s+1)*o),h=Math.floor(i+r-(s+1)),f=c.createLinearGradient(0,h+1,0,h);f.addColorStop(0,u),f.addColorStop(1,l),c.fillStyle=f,c.fillRect(a,h,n,1)}c.strokeStyle="#000",c.strokeRect(a-.5,i-.5,n+1,r+1),o=100/r,c.font="12px sans-serif",c.fillStyle="white",c.textAlign="right";for(var s=0;s<=g.h;s+=r/10)c.fillText(Math.round(s*o)+"",g.x-e-n-e,i+r-s+3)}function o(){var t=8,e=g.x+g.w,n=e+t,r=g.y,i=g.h,a=70;c.clearRect(e+.5,r-10,a,i+20);for(var o,s=x.freq/2/(x.sampCount/2),u=g.h/g.dy,l=u*s,h=[10,25,50],f=1,d=!1;;){for(var p=0;p=p;p+=o){if(p>=u){var m=p-u;if(m>o/2)break;p=u}var v=p*(l/u);v=v>=1e6?numfmt(v/1e6,2)+"M":v>=1e3?numfmt(v/1e3,2)+"k":numfmt(v,1);var y=Math.round(r+i-g.dy*p);if(c.fillText(v,n,y+4),c.beginPath(),c.moveTo(e,y+.5),c.lineTo(e+t/2,y+.5),c.stroke(),p>=u)break}c.font="16px sans-serif",c.save(),c.translate(e+50,g.y+g.h/2),c.rotate(Math.PI/2),c.textAlign="center",c.fillText("Frequency - [Hz]",0,0),c.restore()}function s(){x.interval=+$("#interval").val(),x.freq=2*+$("#freq").val(),x.sampCount=+$("#count").val(),g.dx=+$("#tile-x").val(),g.dy=+$("#tile-y").val()}function u(){c.fillStyle="#000",c.fillRect(g.x,g.y,g.w,g.h),c.strokeStyle="white",c.strokeRect(g.x-.5,g.y-.5,g.w+1,g.h+1)}var c,l,h,f,d,p,m,v={},g={x:50,y:10,w:740,h:512,dx:1,dy:1},x={interval:0,sampCount:0,freq:0},y=!1,b=[[0,0,0,0],[.1,41,17,41],[.25,34,17,78],[.6,17,30,105],[1,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.9,223,217,86],[1.97,248,222,176],[1.99,255,237,222],[2,255,255,255]];return v.init=function(){var t=$("#sg")[0];c=t.getContext("2d"),u(),s(),a(),o(),p=msNow()-1e4,m=msNow()-1e4,$("#count").on("change",function(){var t=+$("#count").val(),e=Math.max(1,g.h/(t/2));$("#tile-x").val(Math.max(4,e)),$("#tile-y").val(e)}),$("#tile-y").on("change",function(){$("#tile-x").val(Math.max(4,$(this).val()))}),$("#go-btn").on("click",function(){y=!y,y?(s(),o(),i()):clearTimeout(l),$("#go-btn").toggleClass("btn-green").toggleClass("btn-red").html(y?"Stop":"Start")})},v}(),page_status=function(){function t(t,a){if(200!=a)errorMsg("Update failed.");else try{var o=JSON.parse(t);n.j=o,$(".sta-only").toggle(o.sta),$(".ap-only").toggle(o.ap),$("#uptime").html(o.uptime),$("#heap").html(o.heap+" bytes"),$("#wmode").html(o.wifiMode),o.sta&&($("#staSSID").html(o.sta.SSID),$("#staRSSIperc").html(o.sta.RSSIperc),$("#staRSSI").html(o.sta.RSSI),$("#staMAC").html(o.sta.MAC)),o.ap&&($("#apSSID").html(o.ap.SSID),$("#apHidden").html(o.ap.hidden?"Yes":"No"),$("#apAuth").html(o.ap.auth),$(".ap-auth-only").toggle("Open"!=o.ap.auth),$("#apPwd").html(o.ap.pwd),$("#apChan").html(o.ap.chan),$("#apMAC").html(o.ap.MAC))}catch(s){errorMsg(s)}i||setTimeout(e,r)}function e(){$().get(_root+"/system/status",t)}var n={};n.j={};var r=1e4,i=!1;return n.trigReset=function(){var t="#reset-modal";$().get(_root+"/system/reset",function(n,r){if(200==r){modal.show(t),i=!0;var a=setInterval(function(){$().get(_root+"/system/ping",function(n,r){200==r&&(modal.hide(t),e(),clearInterval(a),i=!1)},{timeout:500})},1e3)}})},n.init=function(){e()},n}(),page_mon=function(){function t(t){$("#hasref").html(t?"OK":"Not set!")}function e(){var t=$("#rep-svc-xv")[0].checked;t?$(".xv-only").removeClass("hidden"):$(".xv-only").addClass("hidden")}var n={};return n.captureRef=function(){$().get(_root+"/mon/setref",function(e,n){if(200!=n)errorMsg("Operation failed.");else try{var r=JSON.parse(e);t(r.success)}catch(i){errorMsg(i),t(!1)}})},n.compareNow=function(){$().get(_root+"/mon/compare",function(t,e){if(200!=e)errorMsg("Operation failed.");else try{var n=JSON.parse(t);if(!n.success)throw"Capture failed.";$("#actual-dev").html(numfmt(n.deviation,2)),$("#actual-rms").html(numfmt(n.rms,2))}catch(r){errorMsg(r),$("#actual-dev").html("--"),$("#actual-rms").html("--")}})},n.init=function(){e(),$("#rep-svc-xv,#rep-svc-ts").on("change",e),setInterval(function(){$().get(_root+"/mon/status",function(t,e){if(200==e)try{var n=JSON.parse(t);n.success&&($("#actual-dev").html(numfmt(n.deviation,2)),$("#actual-rms").html(numfmt(n.rms,2)))}catch(r){errorMsg(r),$("#actual-dev").html("--"),$("#actual-rms").html("--")}})},1e4)},n}(); \ No newline at end of file +function bool(t){return 1===t||"1"===t||t===!0||"true"===t}function numfmt(t,e){var n=Math.pow(10,e);return Math.round(t*n)/n}function estimateLoadTime(t,e){return 1e3/t*e+1500}function msNow(){return+new Date}function msElapsed(t){return msNow()-t}function copyToClipboard(t){if(!document.execCommand)return!1;var e="_hiddenCopyText_";if(n=document.getElementById(e),!n){var n=document.createElement("textarea");n.style.position="absolute",n.style.left="-9999px",n.style.top="0",n.id=e,document.body.appendChild(n)}n.textContent=t;var r=document.activeElement;n.focus(),n.setSelectionRange(0,n.value.length);var o;try{o=document.execCommand("copy")}catch(u){o=!1}return r&&"function"==typeof r.focus&&r.focus(),n.textContent="",o}function errorMsg(t,e){$("#notif").addClass("error"),notify.show(t,e||3e3)}function infoMsg(t,e){$("#notif").removeClass("error"),notify.show(t,e||3e3)}!function(){"use strict";function t(){var t;for(h=!0,t=0;t=0;n-=1)t(e[n])}function r(t){return t.replace(/-\w/g,function(t){return t.charAt(1).toUpperCase()})}function o(t,e){return t.currentStyle?t.currentStyle[r(e)]:m.getComputedStyle?m.getComputedStyle(t,null).getPropertyValue(e):null}function u(t,e){return encodeURIComponent(t).replace(/%20/g,"+")+"="+encodeURIComponent(e).replace(/%20/g,"+")}function a(t,e,n){try{t.style[r(e)]=n}catch(o){}}function i(t){t.style.display="","none"===o(t,"display")&&(t.style.display="block")}function c(t){var e,r,o,a="";if(t.constructor===Object){for(e in t)if(t.hasOwnProperty(e))if(t[e].constructor===Array)for(r=0;r0&&(a+="&"+u(e.name,e.value));break;case"select-multiple":for(o=0;o0?a.substring(1):""}function f(t,e,r){var o,u,a,i=!1;return t&&(o=t.split(/\s+/),n(function(t){for(a=0;a0?b[0].className.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"").replace(/\s+/," "):void 0},e.setClass=function(t){return(t||""===t)&&n(function(e){e.className=t},b),e},e.addClass=function(t){return t&&n(function(e){e.className+=" "+t},b),e},e.removeClass=function(t){return f(t,"remove",b),e},e.toggleClass=function(t){return f(t,"toggle",b),e},e.hasClass=function(t){return f(t,"has",b)},e.html=function(t){return t||""===t?(n(function(e){e.innerHTML=t},b),e):b[0]?b[0].innerHTML:void 0},e.htmlBefore=function(t){return s(t,"before",b),e},e.htmlAfter=function(t){return s(t,"after",b),e},e.htmlAppend=function(t){return s(t,"append",b),e},e.htmlPrepend=function(t){return s(t,"prepend",b),e},e.attr=function(t,r){if(t){if(t=t.toLowerCase(),"undefined"!=typeof r)return n(function(e){"style"===t?e.style.cssText=r:"class"===t?e.className=r:e.setAttribute(t,r)},b),e;if(b[0])if("style"===t){if(b[0].style.cssText)return b[0].style.cssText}else if("class"===t){if(b[0].className)return b[0].className}else if(b[0].getAttribute(t))return b[0].getAttribute(t)}},e.data=function(t,n){return t?e.attr("data-"+t,n):void 0},e.val=function(t){var r,o,u;if(!_.isUndefined(t))return n(function(e){switch(e.nodeName){case"SELECT":for(("string"==typeof t||"number"==typeof t)&&(t=[t]),o=0;o1?r:r[0];case"INPUT":case"TEXTAREA":case"BUTTON":return b[0].value}},e.checked=function(t){return"boolean"==typeof t?(n(function(e){"INPUT"!==e.nodeName||"checkbox"!==e.type&&"radio"!==e.type||(e.checked=t)},b),e):!b[0]||"INPUT"!==b[0].nodeName||"checkbox"!==b[0].type&&"radio"!==b[0].type?void 0:!!b[0].checked},e.on=function(r,o){return(t===m||t===g)&&(b=[t]),n(function(t){g.addEventListener?t.addEventListener(r,o,!1):g.attachEvent&&(t[r+o]=function(){return o.apply(t,arguments)},t.attachEvent("on"+r,t[r+o]))},b),e},e.off=function(r,o){return(t===m||t===g)&&(b=[t]),n(function(t){g.addEventListener?t.removeEventListener(r,o,!1):g.attachEvent&&(t.detachEvent("on"+r,t[r+o]),t[r+o]=null)},b),e},e.ajax=function(t,e,n,r){var o,u,a=c(b),i=e?e.toUpperCase():"GET";_.isNumber(r)&&(r={timeout:r});var f=_.extend({},{nocache:!0,timeout:5e3,loader:!0},r);if(a&&"GET"===i&&(t+=-1===t.indexOf("?")?"?"+a:"&"+a,a=null),o=new XMLHttpRequest){if(f.nocache){var s=(+new Date).toString(36);t+=(-1===t.indexOf("?")?"?":"&")+"_="+s}f.loader&&$("#loader").addClass("show"),o.open(i,t,!0),o.timeout=f.timeout,u=setTimeout(function(){errorMsg("XHR timed out."),o.abort(),f.loader&&$("#loader").removeClass("show")},f.timeout+10),o.onreadystatechange=function(){4===o.readyState&&(f.loader&&$("#loader").removeClass("show"),n&&0!=o.status&&n(o.responseText,o.status),clearTimeout(u))},o.setRequestHeader("X-Requested-With","XMLHttpRequest"),"POST"===i&&o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o.send(a)}return o},e.get=function(t,n,r){return e.ajax(t,"get",n,r)},e.post=function(t,n,r){return e.ajax(t,"post",n,r)},e}var p=[],d=[],h=!1,v=!1,g=document,m=window;g.addEventListener?(g.addEventListener("DOMContentLoaded",t,!1),m.addEventListener("load",e,!1)):g.attachEvent?(g.attachEvent("onreadystatechange",t),m.attachEvent("onload",e)):m.onload=e,m.$=l}(),function(){function t(t,e){return t.set(e[0],e[1]),t}function e(t,e){return t.add(e),t}function n(t,e,n){var r=n.length;switch(r){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}function r(t,e){for(var n=-1,r=t.length;++n-1&&t%1==0&&e>t}function d(t){for(var e,n=[];!(e=t.next()).done;)n.push(e.value);return n}function h(t){var e=-1,n=Array(t.size);return t.forEach(function(t,r){n[++e]=[r,t]}),n}function v(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=t}),n}function g(t){return $n[t]}function m(){}function y(){}function b(t,e){return _(t,e)&&delete t[e]}function w(t,e){if(ur){var n=t[e];return n===Ce?je:n}return Bn.call(t,e)?t[e]:je}function _(t,e){return ur?t[e]!==je:Bn.call(t,e)}function E(t,e,n){t[e]=ur&&n===je?Ce:n}function j(t){var e=-1,n=t?t.length:0;for(this.clear();++en)return!1;var r=t.length-1;return n==r?t.pop():Qn.call(t,n,1),!0}function R(t,e){var n=U(t,e);return 0>n?je:t[n][1]}function I(t,e){return U(t,e)>-1}function U(t,e){for(var n=t.length;n--;)if(Gt(t[n][0],e))return n;return-1}function F(t,e,n){var r=U(t,e);0>r?t.push([e,n]):t[r][1]=n}function B(t,e,n){var r=t[e];Bn.call(t,e)&&Gt(r,n)&&(n!==je||e in t)||(t[e]=n)}function q(t,e){return t&&mt(e,pe(e),t)}function H(t){return"function"==typeof t?t:we}function W(t){return mr(t)?t:Ht(t)}function D(t,e,n,o,u,a,i){var c;if(o&&(c=a?o(t,u,a,i):o(t)),c!==je)return c;if(!Zt(t))return t;var f=mr(t);if(f){if(c=St(t),!e)return gt(t,c)}else{var s=Nt(t),p=s==Fe||s==Be;if(yr(t))return ft(t,e);if(s==We||s==Me||p&&!a){if(l(t))return a?t:{};if(c=Lt(p?{}:t),!e)return c=q(c,t),n?bt(t,c):c}else{if(!An[s])return a?t:{};c=Mt(t,s,e)}}i||(i=new T);var d=i.get(t);return d?d:(i.set(t,c),(f?r:z)(t,function(r,u){B(c,u,D(r,e,n,o,u,t,i))}),n&&!f?bt(t,c):c)}function X(t){return Zt(t)?Yn(t):{}}function z(t,e){return t&&hr(t,e,pe)}function G(t,e){e=It(e,t)?[e+""]:W(e);for(var n=0,r=e.length;null!=t&&r>n;)t=t[e[n++]];return n&&n==r?t:je}function V(t,e){return Bn.call(t,e)||"object"==typeof t&&e in t&&null===Vn(t)}function J(t,e){return e in Object(t)}function Y(t,e,n,r,o){return t===e?!0:null==t||null==e||!Zt(t)&&!te(e)?t!==t&&e!==e:K(t,e,Y,n,r,o)}function K(t,e,n,r,o,u){var a=mr(t),i=mr(e),c=Pe,f=Pe;a||(c=Nt(t),c=c==Me?We:c),i||(f=Nt(e),f=f==Me?We:f);var s=c==We&&!l(t),p=f==We&&!l(e),d=c==f;if(d&&!s)return u||(u=new T),a||ue(t)?At(t,e,n,r,o,u):xt(t,e,c,n,r,o,u);if(!(o&Te)){var h=s&&Bn.call(t,"__wrapped__"),v=p&&Bn.call(e,"__wrapped__");if(h||v)return u||(u=new T),n(h?t.value():t,v?e.value():e,r,o,u)}return d?(u||(u=new T),$t(t,e,n,r,o,u)):!1}function Q(t,e,n,r){var o=n.length,u=o,a=!r;if(null==t)return!u;for(t=Object(t);o--;){var i=n[o];if(a&&i[2]?i[1]!==t[i[0]]:!(i[0]in t))return!1}for(;++oe&&(e=-e>o?0:o+e),n=n>o?o:n,0>n&&(n+=o),o=e>n?0:n-e>>>0,e>>>=0;for(var u=Array(o);++r1?n[o-1]:je,a=o>2?n[2]:je;for(u="function"==typeof u?(o--,u):je,a&&Rt(n[0],n[1],a)&&(u=3>o?je:u,o=1),e=Object(e);++re?1:-1:ce(r)||0,it(e,n,r,t)}}function At(t,e,n,r,o,u){var i=-1,c=o&Te,f=o&Oe,s=t.length,l=e.length;if(s!=l&&!(c&&l>s))return!1;var p=u.get(t);if(p)return p==e;var d=!0;for(u.set(t,e);++i-1&&t%1==0&&ke>=t}function Zt(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function te(t){return!!t&&"object"==typeof t}function ee(t){return null==t?!1:Kt(t)?Hn.test(Fn.call(t)):te(t)&&(l(t)?Hn:wn).test(t)}function ne(t){return"number"==typeof t||te(t)&&qn.call(t)==He}function re(t){return"string"==typeof t||!mr(t)&&te(t)&&qn.call(t)==ze}function oe(t){return"symbol"==typeof t||te(t)&&qn.call(t)==Ge}function ue(t){return te(t)&&Qt(t.length)&&!!jn[qn.call(t)]}function ae(t){return t===je}function ie(t){if(!t)return 0===t?t:0;if(t=ce(t),t===Ne||t===-Ne){var e=0>t?-1:1;return e*Se}var n=t%1;return t===t?n?t-n:t:0}function ce(t){if(Zt(t)){var e=Kt(t.valueOf)?t.valueOf():t;t=Zt(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(vn,"");var n=bn.test(t);return n||_n.test(t)?On(t.slice(2),n?2:8):yn.test(t)?Le:+t}function fe(t){if("string"==typeof t)return t;if(null==t)return"";if(oe(t))return pr?pr.call(t):"";var e=t+"";return"0"==e&&1/t==-Ne?"-0":e}function se(t,e,n){var r=null==t?je:G(t,e);return r===je?n:r}function le(t,e){return kt(t,e,J)}function pe(t){var e=Ft(t);if(!e&&!Jt(t))return tt(t);var n=Pt(t),r=!!n,o=n||[],u=o.length;for(var a in t)!V(t,a)||r&&("length"==a||p(a,u))||e&&"constructor"==a||o.push(a);return o}function de(t){for(var e=-1,n=Ft(t),r=et(t),o=r.length,u=Pt(t),a=!!u,i=u||[],c=i.length;++e"'`]/g,cn=RegExp(un.source),fn=RegExp(an.source),sn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ln=/^\w*$/,pn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g,dn=/[\\^$.*+?()[\]{}|]/g,hn=RegExp(dn.source),vn=/^\s+|\s+$/g,gn=/\\(\\)?/g,mn=/\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,bn=/^0b[01]+$/i,wn=/^\[object .+?Constructor\]$/,_n=/^0o[0-7]+$/i,En=/^(?:0|[1-9]\d*)$/,jn={};jn[Ye]=jn[Ke]=jn[Qe]=jn[Ze]=jn[tn]=jn[en]=jn[nn]=jn[rn]=jn[on]=!0,jn[Me]=jn[Pe]=jn[Je]=jn[Re]=jn[Ie]=jn[Ue]=jn[Fe]=jn[qe]=jn[He]=jn[We]=jn[De]=jn[Xe]=jn[ze]=jn[Ve]=!1;var An={};An[Me]=An[Pe]=An[Je]=An[Re]=An[Ie]=An[Ye]=An[Ke]=An[Qe]=An[Ze]=An[tn]=An[qe]=An[He]=An[We]=An[De]=An[Xe]=An[ze]=An[Ge]=An[en]=An[nn]=An[rn]=An[on]=!0,An[Ue]=An[Fe]=An[Ve]=!1;var xn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},$n={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Cn={"function":!0,object:!0},On=parseInt,Tn=Cn[typeof exports]&&exports&&!exports.nodeType?exports:je,Nn=Cn[typeof module]&&module&&!module.nodeType?module:je,kn=Nn&&Nn.exports===Tn?Tn:je,Sn=f(Tn&&Nn&&"object"==typeof global&&global),Ln=f(Cn[typeof self]&&self),Mn=f(Cn[typeof window]&&window),Pn=f(Cn[typeof this]&&this),Rn=Sn||Mn!==(Pn&&Pn.window)&&Mn||Ln||Pn||Function("return this")(),In=Array.prototype,Un=Object.prototype,Fn=Function.prototype.toString,Bn=Un.hasOwnProperty,qn=Un.toString,Hn=RegExp("^"+Fn.call(Bn).replace(dn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Wn=kn?Rn.Buffer:je,Dn=Rn.Reflect,Xn=Rn.Symbol,zn=Rn.Uint8Array,Gn=Dn?Dn.enumerate:je,Vn=Object.getPrototypeOf,Jn=Object.getOwnPropertySymbols,Yn=Object.create,Kn=Un.propertyIsEnumerable,Qn=In.splice,Zn=Math.ceil,tr=Object.keys,er=Math.max,nr=Tt(Rn,"Map"),rr=Tt(Rn,"Set"),or=Tt(Rn,"WeakMap"),ur=Tt(Object,"create"),ar=!Kn.call({valueOf:1},"valueOf"),ir=nr?Fn.call(nr):"",cr=rr?Fn.call(rr):"",fr=or?Fn.call(or):"",sr=Xn?Xn.prototype:je,lr=sr?sr.valueOf:je,pr=sr?sr.toString:je,dr=_t(z),hr=Et();Gn&&!Kn.call({valueOf:1},"valueOf")&&(et=function(t){return d(Gn(t))});var vr=ut("length"),gr=Jn||function(){return[]};(nr&&Nt(new nr)!=qe||rr&&Nt(new rr)!=Xe||or&&Nt(new or)!=Ve)&&(Nt=function(t){var e=qn.call(t),n=e==We?t.constructor:null,r="function"==typeof n?Fn.call(n):"";if(r)switch(r){case ir:return qe;case cr:return Xe;case fr:return Ve}return e});var mr=Array.isArray,yr=Wn?function(t){return t instanceof Wn}:be(!1),br=wt(function(t,e){if(ar||Ft(e)||Jt(e))return void mt(e,de(e),t);for(var n in e)B(t,n,e[n])}),wr=jt();y.prototype=ur?ur(null):Un,j.prototype.clear=A,j.prototype["delete"]=x,j.prototype.get=$,j.prototype.has=C,j.prototype.set=O,T.prototype.clear=N,T.prototype["delete"]=k,T.prototype.get=S,T.prototype.has=L,T.prototype.set=M,m.assignIn=br,m.constant=be,m.iteratee=_e,m.keys=pe,m.keysIn=de,m.map=Xt,m.property=Ee,m.range=wr,m.rest=zt,m.toPairs=he,m.extend=br,m.eq=Gt,m.escape=ve,m.escapeRegExp=ge,m.forEach=Dt,m.get=se,m.hasIn=le,m.identity=we,m.isArguments=Vt,m.isArray=mr,m.isArrayLike=Jt,m.isArrayLikeObject=Yt,m.isBuffer=yr,m.isFunction=Kt,m.isLength=Qt,m.isNative=ee,m.isNumber=ne,m.isObject=Zt,m.isObjectLike=te,m.isString=re,m.isSymbol=oe,m.isTypedArray=ue,m.isUndefined=ae,m.last=Wt,m.replace=me,m.toInteger=ie,m.toNumber=ce,m.toString=fe,m.unescape=ye,m.each=Dt,m.VERSION=Ae,(Mn||Ln||{})._=m,Rn._=m}.call(this),Math.log10=Math.log10||function(t){return Math.log(t)/Math.LN10},String.prototype.format=function(){var t=this,e=arguments;1==arguments.length&&(_.isArray(arguments[0])||_.isObject(arguments[0]))&&(e=arguments[0]);for(var n in e)if(e.hasOwnProperty(n)){var r=n;n.match(/^\{.*\}$/)||(n="{"+n+"}");var o=new RegExp(_.escapeRegExp(n),"g");t=t.replace(o,e[r])}return t};var modal=function(){var t={};return t.show=function(t){var e=$(t);e.removeClass("hidden visible"),setTimeout(function(){e.addClass("visible")},1)},t.hide=function(t){var e=$(t);e.removeClass("visible"),setTimeout(function(){e.addClass("hidden")},500)},t.init=function(){$(".Modal").on("click",function(){$(this).hasClass("no-close")||t.hide(this)}),$(".Dialog").on("click",function(t){t.stopImmediatePropagation()}),$(window).on("keydown",function(e){27==e.which&&t.hide(".Modal")})},t}(),notify=function(){var t,e,n={},r="#notif";return n.show=function(o,u){$(r).html(o),modal.show(r),clearTimeout(t),clearTimeout(e),_.isUndefined(u)||(t=setTimeout(n.hide,u))},n.hide=function(){var t=$(r);t.removeClass("visible"),e=setTimeout(function(){t.addClass("hidden")},250)},n.init=function(){$(r).on("click",function(){n.hide(this)})},n}();$().ready(function(){setInterval(function(){$(".anim-dots").each(function(t){var e=$(t),n=e.html()+".";5==n.length&&(n="."),e.html(n)})},1e3),$("input[type=number]").on("mousewheel",function(t){var e=+$(this).val(),n=+($(this).attr("step")||1),r=$(this).attr("min"),o=$(this).attr("max");if(t.wheelDelta>0?e+=n:e-=n,_.isUndefined(r)||(e=Math.max(e,r)),_.isUndefined(o)||(e=Math.min(e,o)),$(this).val(e),"createEvent"in document){var u=document.createEvent("HTMLEvents");u.initEvent("change",!1,!0),$(this)[0].dispatchEvent(u)}else $(this)[0].fireEvent("onchange");t.preventDefault()}),modal.init(),notify.init()});var page_wifi=function(){function t(t,e){if(200!=e)return void n(5e3);t=JSON.parse(t);var u=!bool(t.result.inProgress)&&t.result.APs.length>0;if(n(u?15e3:1e3),u){var a=$("#ap-list");$(".AP").remove(),a.toggle(u),$("#ap-loader").toggle(!u),t.result.APs.sort(function(t,e){return e.rssi-t.rssi}).forEach(function(t){if(t.enc=parseInt(t.enc),!(t.enc>4)){var e=document.createElement("div"),n=$(e).data("ssid",t.essid).data("pwd",0!=t.enc).addClass("AP");t.essid==r.current&&n.addClass("selected");var u=document.createElement("div");$(u).addClass("inner").htmlAppend('
{0}
'.format(t.rssi_perc)).htmlAppend('
{0}
'.format(_.escape(t.essid))).htmlAppend('
{0}
'.format(o[t.enc]));n.on("click",function(){var t=$(this);$("#conn-essid").val(t.data("ssid")),$("#conn-passwd").val(""),t.data("pwd")?modal.show("#psk-modal"):$("#conn-form").submit()}),e.appendChild(u),a[0].appendChild(e)}})}}function e(){$().get(_root+"/wifi/scan",t)}function n(t){setTimeout(e,t)}var r={},o=["Open","WEP","WPA","WPA2","WPA/WPA2"];return r.init=function(){e()},r}(),page_home=function(){var t={};return t.init=function(){},t}(); \ No newline at end of file diff --git a/html/pages/about.tpl b/html/pages/about.tpl deleted file mode 100644 index ef9c9cb..0000000 --- a/html/pages/about.tpl +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - About - Current Analyser - - - - - - -
- -
- Loading… - -

About

- -
- -

Current Analyser

- - - -

© Ondřej Hruška, 2016 <ondra@ondrovo.com>

- -

Katedra měření, FEL ČVUT
Department of Measurement, FEE CTU

-
- -
-

Firmware

- - - - - - - - - - - - - - - - - - - - - - -
Firmwarev%vers_fw%, build %date% at %time%
esp-httpd libv%vers_httpd%
SBMP libv%vers_sbmp%
ESP IoT SDKv%vers_sdk%
STM32 firmwarev%vers_stm%
- -

- The webserver was built using the great esp-httpd - library by Jeroen Domburg. -

-
- - - - -
-
- - diff --git a/html/pages/fft.html b/html/pages/fft.html deleted file mode 100644 index fc51201..0000000 --- a/html/pages/fft.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - FFT - Current Analyser - - - - - - -
- -
- Loading… - -

FFT

- -
-
- - -
-
- - - Hz -
-
- Load -
-
- -
-
-
- - - - - - - - - - - - - - - - - -
Samples
fs
Ipeak
IRMS
-
-  ms - -
-
-
- - - - - - - - -
-
- - diff --git a/html/pages/home.tpl b/html/pages/home.tpl new file mode 100644 index 0000000..7ba4719 --- /dev/null +++ b/html/pages/home.tpl @@ -0,0 +1,49 @@ + + + + + + + + Home - WiFi Demo + + + + + + +
+ +
+ Loading… + +

Home

+ +
+

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.

+
+ +
+

Firmware

+

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.

+
+ + + + + + +
+
+ + diff --git a/html/pages/monitoring.tpl b/html/pages/monitoring.tpl deleted file mode 100644 index 11b7726..0000000 --- a/html/pages/monitoring.tpl +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - Monitoring - Current Analyser - - - - - - -
- -
- Loading… - -

Monitoring & Reporting

- -
-

Status

- - - - - - - - - -
Reference: - %refStored% - Capture -
Status: - - Δ = %curDeviation%
- IRMS = %curRMS% mA -
- Measure -
-
- -
-

Reporting

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
-   -
-  seconds -
Service: -    -   -
 
-
-
- - - - - - -
-
- - diff --git a/html/pages/sgm.html b/html/pages/sgm.html deleted file mode 100644 index cd8b5a9..0000000 --- a/html/pages/sgm.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - Spectrogram - Current Analyser - - - - - - -
- -
- Loading… - -

Spectrogram

- -
-
- - -
-
- - - × - -
-
- - - Hz -
-
- - - ms -
-
- Start -
-
- -
- -
- - - - - - -
-
- - diff --git a/html/pages/status.tpl b/html/pages/status.tpl deleted file mode 100644 index 46dfacb..0000000 --- a/html/pages/status.tpl +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - Home - Current Analyser - - - - - - -
- -
- Loading… - -

System Status

- -
-

Runtime

- - - - - - - - - - - - - -
Uptime:%uptime%
Free heap:%heap%
Restart system
-
- -
-

WiFi

- - - - - -
WiFi mode:%wifiMode%
-
- - - - - - - - - - - - - - -
-
- - diff --git a/html/pages/wfm.html b/html/pages/wfm.html deleted file mode 100644 index a71c59d..0000000 --- a/html/pages/wfm.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - Waveform - Current Analyser - - - - - - -
- -
- Loading… - -

Waveform

- -
-
- - -
-
- - - Hz -
-
- Load -
-
- -
-
-
- - - - - - - - - - - - - - - - - -
Samples
fs
Ipeak
IRMS
-
-  ms - -
-
-
- - - - - - - - -
-
- - diff --git a/html/pages/wifi.tpl b/html/pages/wifi.tpl index 192ecb4..31308dc 100644 --- a/html/pages/wifi.tpl +++ b/html/pages/wifi.tpl @@ -5,7 +5,7 @@ - WiFi config - Current Analyser + WiFi config - WiFi Demo @@ -18,8 +18,8 @@
+
WiFi Demo
+ HomeWiFi config
Loading… diff --git a/html_src/_start.php b/html_src/_start.php index 862790a..0f9b0af 100644 --- a/html_src/_start.php +++ b/html_src/_start.php @@ -4,17 +4,11 @@ $root = $prod ? '' : 'http://192.168.1.13'; $menu = [ - 'home' => [ $prod ? '/status' : '/page_status.php', 'Home' ], - 'wifi' => [ $prod ? '/wifi' : '/page_wifi.php', 'WiFi config' ], - 'waveform' => [ $prod ? '/waveform' : '/page_waveform.php', 'Waveform' ], - 'fft' => [ $prod ? '/fft' : '/page_fft.php', 'FFT' ], - 'spectrogram' => [ $prod ? '/spectrogram' : '/page_spectrogram.php','Spectrogram' ], - 'monitoring' => [ $prod ? '/monitoring' : '/page_monitoring.php', 'Monitoring' ], - // 'transient' => [ '/transient', 'Power-on transient' ], - 'about' => [ $prod ? '/about' : '/page_about.php', 'About' ], + 'home' => [ $prod ? '/home' : '/page_home.php', 'Home' ], + 'wifi' => [ $prod ? '/wifi' : '/page_wifi.php', 'WiFi config' ], ]; - $appname = 'Current Analyser'; + $appname = 'WiFi Demo'; function e($s) { return htmlspecialchars($s, ENT_HTML5|ENT_QUOTES); diff --git a/html_src/css/app.css b/html_src/css/app.css index 09d0a23..8040cd9 100644 --- a/html_src/css/app.css +++ b/html_src/css/app.css @@ -1 +1 @@ -*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}figure,nav{display:block}canvas,progress{display:inline-block;vertical-align:baseline}[hidden]{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b{font-weight:700}h1,h2{font-size:2em;margin:.67em 0}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,pre{font-family:monospace;font-size:1em}button,input,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}legend{border:0;padding:0}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}.ct-zoom-rect{fill:rgba(200,100,100,.3);stroke:#ff2b12}.ct-axis-title{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ct-axis-title,.ct-label{fill:rgba(255,255,255,.8)}.ct-label{color:rgba(255,255,255,.8);font-size:.75rem;line-height:1}.ct-label.ct-horizontal.ct-start{align-items:flex-end;justify-content:flex-start;text-align:left;text-anchor:start}.ct-label.ct-horizontal.ct-end{align-items:flex-start;justify-content:flex-start;text-align:left;text-anchor:start;transform:translate(-4px) rotate(45deg)}.ct-label.ct-vertical.ct-start{align-items:flex-end;justify-content:flex-end;text-align:right;text-anchor:end;transform:translateY(20%)}.ct-label.ct-vertical.ct-end{align-items:flex-end;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar .ct-label,.ct-chart-line .ct-label{display:flex}.ct-chart-bar .ct-label.ct-horizontal.ct-start{align-items:flex-end;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar .ct-label.ct-horizontal.ct-end{align-items:flex-start;justify-content:center;text-align:center;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-start{align-items:flex-end;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-horizontal.ct-end{align-items:flex-start;justify-content:flex-start;text-align:left;text-anchor:start}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-start{align-items:center;justify-content:flex-end;text-align:right;text-anchor:end}.ct-chart-bar.ct-horizontal-bars .ct-label.ct-vertical.ct-end{align-items:center;justify-content:flex-start;text-align:left;text-anchor:end}.ct-grid{stroke:rgba(255,255,255,.3);stroke-width:1px;stroke-dasharray:2px}.ct-point{stroke-width:4px;stroke-linecap:round}.ct-line{fill:none;stroke-width:2px}.ct-with-area .ct-line{stroke-width:1px}.ct-area{stroke:none;fill-opacity:.3}.ct-bar{fill:none;stroke-width:10px}.ct-series-a .ct-bar,.ct-series-a .ct-line,.ct-series-a .ct-point{stroke:#f05b4f}.ct-series-a .ct-area,.ct-series-a .ct-slice-pie{fill:#f05b4f}.ct-series-b .ct-bar,.ct-series-b .ct-line,.ct-series-b .ct-point{stroke:#6188e2}.ct-series-b .ct-area,.ct-series-b .ct-slice-pie{fill:#6188e2}.ct-series-c .ct-bar,.ct-series-c .ct-line,.ct-series-c .ct-point{stroke:#59922b}.ct-series-c .ct-area,.ct-series-c .ct-slice-pie{fill:#59922b}.ct-series-d .ct-bar,.ct-series-d .ct-line,.ct-series-d .ct-point{stroke:#eacf7d}.ct-series-d .ct-area,.ct-series-d .ct-slice-pie{fill:#eacf7d}.ct-series-e .ct-bar,.ct-series-e .ct-line,.ct-series-e .ct-point{stroke:#a748ca}.ct-series-e .ct-area,.ct-series-e .ct-slice-pie{fill:#a748ca}.ct-wide{display:block;position:relative;width:100%}.ct-wide:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:62.5%}.ct-wide:after{content:"";display:table;clear:both}.ct-wide>svg{display:block;position:absolute;top:0;left:0}.ct-narrow{display:block;position:relative;width:100%}.ct-narrow:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:66.6666666667%}.ct-narrow:after{content:"";display:table;clear:both}.ct-narrow>svg{display:block;position:absolute;top:0;left:0}.center{text-align:center}.invis{visibility:hidden!important}.hidden{display:none!important}.nb{font-weight:400}html{font-family:Arial,sans-serif;color:#D0D0D0;background:#131315}body,html{border:0 none;margin:0;padding:0;text-decoration:none;width:100%;height:100%;overflow:hidden}a,a:link,a:visited{cursor:pointer;color:#5abfff;text-decoration:none}a:hover{color:#5abfff;text-decoration:underline}.chartexport a{background:#3b7299;border-radius:3px;padding:5px;color:#0c171e;text-decoration:none}.chartexport a:hover{background:#4ea6dd}.chartexport a:active{position:relative;top:1px}.chartexport textarea{margin-top:10px;width:100%;height:10em;resize:vertical}#outer{display:flex;position:absolute;width:100%;height:100%;left:0;right:0;top:0;bottom:0;overflow:hidden;flex-direction:row}@media screen and (max-width:544px){#outer{display:block;overflow-y:scroll}}#menu{flex:0 0 15rem;background:#2bab5f}#menu>*{display:block;text-decoration:none;padding:.6180469716rem 1rem;white-space:nowrap;word-wrap:normal;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#menu #brand{color:white;background:#218248;font-size:120%;text-align:center;position:relative;margin-bottom:1rem}@media screen and (max-width:544px){#menu #brand{background:#2bab5f;cursor:pointer}#menu #brand:after{position:absolute;color:rgba(0,0,0,.2);right:1rem;content:'>';top:50%;font-size:120%;font-weight:700;transform:translateY(-50%) rotate(90deg)}}#menu.expanded #brand{background:#218248}@media screen and (max-width:544px){#menu.expanded #brand:after{transform:translateY(-50%) rotate(-90deg)}}#menu a{font-size:130%;color:white;transition:background-color .2s;text-shadow:0 0 5px rgba(0,0,0,.4)}#menu a.selected,#menu a:hover{background:#1bd886;text-shadow:0 0 5px rgba(0,0,0,.6)}#menu a.selected{position:relative;box-shadow:0 0 5px rgba(0,0,0,.5)}#menu a:before{content:"▸";padding-right:.5rem;position:relative;top:-.1rem}@media screen and (max-width:544px){#menu a{display:none}}#menu.expanded a{display:block}@media screen and (min-width:545px) and (max-width:1000px){#menu{flex-basis:10rem}#menu #brand{font-size:95%;margin-bottom:.6180469716rem}#menu a{font-size:105%}#menu>*{padding:.3819820591rem .6180469716rem}}#content{flex-grow:1;position:relative;padding:1rem;overflow-y:auto}@media screen and (max-width:544px){#content{padding:.6180469716rem}}#content>*{margin-left:auto;margin-right:auto}#content h1{text-align:center;font-size:2.2806973457em;margin-top:0;margin-bottom:1rem}#content h2{font-size:1.423828125em;margin-bottom:.6180469716rem}#content td,#content th{padding:.3819820591rem}#content tbody th{text-align:right;width:130px;color:#fff}#loader{position:absolute;right:1.618rem;top:1.618rem;transition:opacity .2s;opacity:0}@media screen and (max-width:544px){#loader{top:1rem;right:1rem}}#loader.show{opacity:1}.Box{display:block;max-width:900px;margin-top:1rem;padding:.6180469716rem 1rem;border-radius:3px;background-color:rgba(255,255,255,.07)}@media screen and (max-width:544px){.Box{margin-top:.6180469716rem}}.Box h2,h1+.Box{margin-top:0}.Box.wide{width:initial;max-width:initial}.Box.medium{max-width:1200px}.Box .Valfield{display:inline-block;min-width:10em}.Modal{position:fixed;width:100%;height:100%;left:0;top:0;right:0;bottom:0;display:flex;justify-content:center;align-items:center;transition:opacity .5s;background:rgba(0,0,0,.65);opacity:0}.Modal.visible{opacity:1}.Modal.hidden{display:none}.Dialog{margin:.6180469716rem;padding:1rem;overflow:hidden;max-width:100%;max-height:100%;flex:0 1 30rem;background:#1c1c1e;border-left:6px solid #217b3a;border-right:6px solid #217b3a;box-shadow:0 0 2px 0 #434349,0 0 6px 0 black;border-radius:6px}.Dialog h1,.Dialog h2{margin-top:0}.Dialog p:last-child{margin-bottom:0}.NotifyMsg{position:fixed;bottom:2.617924rem;padding:.6180469716rem 1rem;left:50%;transform:translate(-50%);-webkit-font-smoothing:subpixel-antialiased;-webkit-transform:translateZ(0) scale(1);background:#37a349;color:white;text-shadow:0 0 2px black;box-shadow:0 0 6px 0 rgba(0,0,0,.6);border-radius:5px;max-width:80%;transition:opacity .5s;opacity:0}.NotifyMsg.error{background:#d03e42}@media screen and (max-width:544px){.NotifyMsg{width:calc(100% - 1rem)}}.NotifyMsg.visible{opacity:1}.NotifyMsg.hidden{display:none}.button,button,input[type=button],input[type=reset],input[type=submit]{text-align:center;cursor:pointer;display:inline-block;border-radius:2px;padding:0 .6em;border:0 none;outline:0 none!important;line-height:1.8em;font-size:1.1em;margin-bottom:3px;min-width:5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-shadow:1.5px 1.5px 2px rgba(0,0,0,.8)}.button:active,button:active,input[type=button]:active,input[type=reset]:active,input[type=submit]:active{position:relative;top:2px}.button.narrow,button.narrow,input[type=button].narrow,input[type=reset].narrow,input[type=submit].narrow{min-width:initial}.btn-green,input[type=submit]{background-color:#2ca94b;box-shadow:0 3px 0 #1d7032;text-decoration:none!important}.btn-green,.btn-green:link,.btn-green:visited,input[type=submit],input[type=submit]:link,input[type=submit]:visited{color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:active,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:active,input[type=submit]:hover{background-color:#28ba5c;color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:hover{box-shadow:0 3px 0 #1a773b}.btn-green:active,input[type=submit]:active{box-shadow:0 1px 0 #1a773b}.btn-red,input[type=reset]{background-color:#D04E51;box-shadow:0 3px 0 #aa2d30;text-decoration:none!important}.btn-red,.btn-red:link,.btn-red:visited,input[type=reset],input[type=reset]:link,input[type=reset]:visited{color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:active,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:active,input[type=reset]:hover{background-color:#d4403f;color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:hover{box-shadow:0 3px 0 #9e2423}.btn-red:active,input[type=reset]:active{box-shadow:0 1px 0 #9e2423}.btn-blue{background-color:#3983cd;box-shadow:0 3px 0 #265f98;text-decoration:none!important}.btn-blue,.btn-blue:link,.btn-blue:visited{color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:active,.btn-blue:hover{background-color:#2076C6;color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:hover{box-shadow:0 3px 0 #154c80}.btn-blue:active{box-shadow:0 1px 0 #154c80}input[type=number],input[type=password],input[type=text],select,textarea{border:0 none;border-bottom:2px solid #217b3a;background-color:#303030;color:#fff;padding:6px;line-height:1em;outline:0 none!important;-moz-outline:0 none!important;font-weight:400}input[type=number]:focus,input[type=number]:hover,input[type=password]:focus,input[type=password]:hover,input[type=text]:focus,input[type=text]:hover,select:focus,select:hover,textarea:focus,textarea:hover{border-bottom-color:#28bc65}input[type=number],input[type=password],input[type=text],textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;cursor:text}textarea{font-family:monospace;line-height:1.2em;display:block}form{border:0 none;margin:0;padding:0;text-decoration:none}input[type=number],input[type=password],input[type=text],label.select-wrap,select,textarea{width:250px}form .Row{vertical-align:middle;margin:14px auto;text-align:left;display:flex;flex-direction:row}form .Row:first-child{margin-top:0}form .Row:last-child{margin-bottom:0}form .Row .spacer{width:130px}@media screen and (max-width:544px){form .Row .spacer{display:none}}form .Row.buttons .button,form .Row.buttons input{margin-right:.6180469716rem}form .Row.centered{justify-content:center}form .Row.message{font-size:1em;text-shadow:1px 1px 3px black;text-align:center}form .Row.message.error{color:crimson}form .Row.message.ok{color:#0fe851}form .Row.separator{padding-top:14px;border-top:2px solid rgba(255,255,255,.1)}form .Row textarea{display:inline-block;vertical-align:top;min-height:10rem;flex-grow:1;resize:vertical}form .Row label{font-weight:700;color:#fff;text-shadow:1px 1px 3px black;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}form .Row .checkbox-wrap,form .Row label{display:inline-block;width:130px;text-align:right;padding:8px;align-self:flex-start}form .Row .checkbox-wrap input[type=checkbox]{margin:auto;width:auto;height:auto}form .Row .checkbox-wrap+label{width:250px;padding-left:0;text-align:left;cursor:pointer}@media screen and (max-width:544px){form .Row{flex-direction:column}form .Row.buttons,form .Row.centered{flex-direction:row}form .Row.buttons{justify-content:center}form .Row.buttons :last-child{margin-right:0}form .Row label{padding-left:0;text-align:left;width:auto}form .Row .checkbox-wrap{order:1;text-align:left;padding-bottom:0;border-radius:.4px;width:auto}form .Row .checkbox-wrap+label{width:auto}form .Row input[type=number],form .Row input[type=password],form .Row input[type=text],form .Row textarea{width:100%}}form span.required{color:red}.RadioGroup{display:inline-block;line-height:1.5em;vertical-align:middle}.RadioGroup label{width:auto;text-align:left;cursor:pointer;font-weight:400}.RadioGroup input[type=radio]{vertical-align:middle;margin:0 0 0 5px}@media screen and (-webkit-min-device-pixel-ratio:0){select{padding-right:18px}}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;line-height:1.2em;padding-right:1em}select:-moz-focusring{color:transparent;text-shadow:0 0 0 #fff}select option{background:#303030}label.select-wrap{position:relative;display:inline!important;margin:0!important;padding:0!important;width:auto!important}label.select-wrap:after{content:'<>';font-family:Consolas,monospace;font-weight:700;color:#28bc65;top:50%;transform:translateY(-50%) rotate(90deg);right:2px;position:absolute;z-index:100;pointer-events:none}#ap-list{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:0;-moz-column-gap:0;column-gap:0;margin:0 -.2360828548rem}@media screen and (min-width:545px) and (max-width:1000px){#ap-list{-webkit-column-count:2;-moz-column-count:2;column-count:2}}@media screen and (max-width:544px){#ap-list{-webkit-column-count:1;-moz-column-count:1;column-count:1}}#ap-loader{background:rgba(255,255,255,.1);border-radius:5px;padding:.3819820591rem;margin-bottom:.3819820591rem}#ap-box{padding-bottom:.3819820591rem}#psk-modal form{display:flex;align-items:center;margin:.3819820591rem}#psk-modal form>*{margin-left:.3819820591rem;margin-right:.3819820591rem}#psk-modal form>:first-child{margin-left:0}#psk-modal form>:last-child{margin-right:0}#psk-modal form input[type=password]{min-width:5rem}.AP{-webkit-column-break-inside:avoid;page-break-inside:avoid;break-inside:avoid-column;max-width:500px;padding:.2360828548rem}.AP.selected .inner{background:#43de81!important;cursor:default;top:0!important}.AP .inner{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;border-radius:3px;color:#222;background:#afafaf;transition:background-color .5s;display:flex}.AP .inner:active{left:0;top:1px}.AP .inner:hover{background:white}.AP .inner>*{padding:.6180469716rem;white-space:nowrap;word-wrap:normal}.AP .inner .rssi{min-width:2rem;flex:0 0 15%;text-align:right}.AP .inner .rssi:after{padding-left:.090179415rem;content:'%';font-size:.8888888889em}.AP .inner .essid{flex:1 1 70%;min-width:0;text-overflow:ellipsis;overflow:hidden;font-weight:700}.AP .inner .auth{flex:0 0 15%}.page-home #staRSSIperc:after{padding-left:.1459102934rem;content:'%';font-size:.8888888889em}.page-home #staRSSI:after{padding-left:.1459102934rem;content:'dBm';font-size:.8888888889em}#samp-ctrl{display:flex;padding:.3819820591rem;flex-direction:row;justify-content:center;align-items:stretch}@media screen and (max-width:544px){#samp-ctrl{flex-direction:column}}#samp-ctrl>div{margin:.3819820591rem .6180469716rem}#samp-ctrl label{line-height:1.8;font-weight:700}#samp-ctrl input,#samp-ctrl select{width:6em}@media screen and (max-width:544px){#samp-ctrl input,#samp-ctrl select{width:100%}}#samp-ctrl #tile-cfg input{width:3em}#samp-ctrl #interval{width:4.5em}.Box.chartbox{display:flex;flex-direction:row}@media screen and (max-width:544px){.Box.chartbox{flex-direction:column}}.Box.chartbox .stats{flex:0 1;position:relative;padding-bottom:50px}@media screen and (max-width:544px){.Box.chartbox .stats table{margin:0 auto}.Box.chartbox .stats td,.Box.chartbox .stats th{width:50%}}.Box.chartbox .stats td,.Box.chartbox .stats th{white-space:nowrap;word-wrap:normal}.Box.chartbox .stats th sub{font-weight:400}.Box.chartbox .stats td{min-width:100px}.Box.chartbox .stats td:after{font-size:90%;padding-left:.5em}.Box.chartbox .stats #stat-f-s:after{content:"Hz"}.Box.chartbox .stats #stat-i-peak:after,.Box.chartbox .stats #stat-i-rms:after{content:"mA"}.Box.chartbox .stats .ar{position:absolute;bottom:.3819820591rem;width:100%;text-align:center}.Box.chartbox .stats .ar input[type=number]{width:4em}.Box.chartbox .stats .ar input[type=button]{margin-left:.3819820591rem}.page-about .Box{padding-left:1rem;padding-right:1rem}.page-about .Box a{font-weight:700}.page-about #logo{float:right;height:130px}.page-about #logo2{max-width:150px}@media screen and (min-width:545px){.mq-phone{display:none}}@media screen and (max-width:544px){.mq-tablet-min{display:none}}@media screen and (min-width:1001px){.mq-tablet-max{display:none}}@media screen and (max-width:1000px){.mq-normal-min{display:none}} \ No newline at end of file +*,:after,:before{box-sizing:border-box}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}figure,nav{display:block}canvas,progress{display:inline-block;vertical-align:baseline}[hidden]{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b{font-weight:700}h1,h2{font-size:2em;margin:.67em 0}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,pre{font-family:monospace;font-size:1em}button,input,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}legend{border:0;padding:0}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}.center{text-align:center}.invis{visibility:hidden!important}.hidden{display:none!important}.nb{font-weight:400}html{font-family:Arial,sans-serif;color:#D0D0D0;background:#131315}body,html{border:0 none;margin:0;padding:0;text-decoration:none;width:100%;height:100%;overflow:hidden}a,a:link,a:visited{cursor:pointer;color:#5abfff;text-decoration:none}a:hover{color:#5abfff;text-decoration:underline}.chartexport a{background:#3b7299;border-radius:3px;padding:5px;color:#0c171e;text-decoration:none}.chartexport a:hover{background:#4ea6dd}.chartexport a:active{position:relative;top:1px}.chartexport textarea{margin-top:10px;width:100%;height:10em;resize:vertical}#outer{display:flex;position:absolute;width:100%;height:100%;left:0;right:0;top:0;bottom:0;overflow:hidden;flex-direction:row}@media screen and (max-width:544px){#outer{display:block;overflow-y:scroll}}#menu{flex:0 0 15rem;background:#2c6cab}#menu>*{display:block;text-decoration:none;padding:.6180469716rem 1rem;white-space:nowrap;word-wrap:normal;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#menu #brand{color:white;background:#225282;font-size:120%;text-align:center;position:relative;margin-bottom:1rem}@media screen and (max-width:544px){#menu #brand{background:#2c6cab;cursor:pointer}#menu #brand:after{position:absolute;color:rgba(0,0,0,.2);right:1rem;content:'>';top:50%;font-size:120%;font-weight:700;transform:translateY(-50%) rotate(90deg)}}#menu.expanded #brand{background:#225282}@media screen and (max-width:544px){#menu.expanded #brand:after{transform:translateY(-50%) rotate(-90deg)}}#menu a{font-size:130%;color:white;transition:background-color .2s;text-shadow:0 0 5px rgba(0,0,0,.4)}#menu a.selected,#menu a:hover{background:#1c79d6;text-shadow:0 0 5px rgba(0,0,0,.6)}#menu a.selected{position:relative;box-shadow:0 0 5px rgba(0,0,0,.5)}#menu a:before{content:"▸";padding-right:.5rem;position:relative;top:-.1rem}@media screen and (max-width:544px){#menu a{display:none}}#menu.expanded a{display:block}@media screen and (min-width:545px) and (max-width:1000px){#menu{flex-basis:10rem}#menu #brand{font-size:95%;margin-bottom:.6180469716rem}#menu a{font-size:105%}#menu>*{padding:.3819820591rem .6180469716rem}}#content{flex-grow:1;position:relative;padding:1rem;overflow-y:auto}@media screen and (max-width:544px){#content{padding:.6180469716rem}}#content>*{margin-left:auto;margin-right:auto}#content h1{text-align:center;font-size:2.2806973457em;margin-top:0;margin-bottom:1rem}#content h2{font-size:1.423828125em;margin-bottom:.6180469716rem}#content td,#content th{padding:.3819820591rem}#content tbody th{text-align:right;width:130px;color:#fff}#loader{position:absolute;right:1.618rem;top:1.618rem;transition:opacity .2s;opacity:0}@media screen and (max-width:544px){#loader{top:1rem;right:1rem}}#loader.show{opacity:1}.Box{display:block;max-width:900px;margin-top:1rem;padding:.6180469716rem 1rem;border-radius:3px;background-color:rgba(255,255,255,.07)}@media screen and (max-width:544px){.Box{margin-top:.6180469716rem}}.Box h2,h1+.Box{margin-top:0}.Box.wide{width:initial;max-width:initial}.Box.medium{max-width:1200px}.Box .Valfield{display:inline-block;min-width:10em}.Modal{position:fixed;width:100%;height:100%;left:0;top:0;right:0;bottom:0;display:flex;justify-content:center;align-items:center;transition:opacity .5s;background:rgba(0,0,0,.65);opacity:0}.Modal.visible{opacity:1}.Modal.hidden{display:none}.Dialog{margin:.6180469716rem;padding:1rem;overflow:hidden;max-width:100%;max-height:100%;flex:0 1 30rem;background:#1c1c1e;border-left:6px solid #214e7a;border-right:6px solid #214e7a;box-shadow:0 0 2px 0 #434349,0 0 6px 0 black;border-radius:6px}.Dialog h1,.Dialog h2{margin-top:0}.Dialog p:last-child{margin-bottom:0}.NotifyMsg{position:fixed;bottom:2.617924rem;padding:.6180469716rem 1rem;left:50%;transform:translate(-50%);-webkit-font-smoothing:subpixel-antialiased;-webkit-transform:translateZ(0) scale(1);background:#37a349;color:white;text-shadow:0 0 2px black;box-shadow:0 0 6px 0 rgba(0,0,0,.6);border-radius:5px;max-width:80%;transition:opacity .5s;opacity:0}.NotifyMsg.error{background:#d03e42}@media screen and (max-width:544px){.NotifyMsg{width:calc(100% - 1rem)}}.NotifyMsg.visible{opacity:1}.NotifyMsg.hidden{display:none}.button,button,input[type=button],input[type=reset],input[type=submit]{text-align:center;cursor:pointer;display:inline-block;border-radius:2px;padding:0 .6em;border:0 none;outline:0 none!important;line-height:1.8em;font-size:1.1em;margin-bottom:3px;min-width:5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-shadow:1.5px 1.5px 2px rgba(0,0,0,.8)}.button:active,button:active,input[type=button]:active,input[type=reset]:active,input[type=submit]:active{position:relative;top:2px}.button.narrow,button.narrow,input[type=button].narrow,input[type=reset].narrow,input[type=submit].narrow{min-width:initial}.btn-green,input[type=submit]{background-color:#2ca94b;box-shadow:0 3px 0 #1d7032;text-decoration:none!important}.btn-green,.btn-green:link,.btn-green:visited,input[type=submit],input[type=submit]:link,input[type=submit]:visited{color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:active,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:active,input[type=submit]:hover{background-color:#28ba5c;color:#FEFEFE}.btn-green.active,.btn-green.selected,.btn-green:hover,input[type=submit].active,input[type=submit].selected,input[type=submit]:hover{box-shadow:0 3px 0 #1a773b}.btn-green:active,input[type=submit]:active{box-shadow:0 1px 0 #1a773b}.btn-red,input[type=reset]{background-color:#D04E51;box-shadow:0 3px 0 #aa2d30;text-decoration:none!important}.btn-red,.btn-red:link,.btn-red:visited,input[type=reset],input[type=reset]:link,input[type=reset]:visited{color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:active,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:active,input[type=reset]:hover{background-color:#d4403f;color:#FEFEFE}.btn-red.active,.btn-red.selected,.btn-red:hover,input[type=reset].active,input[type=reset].selected,input[type=reset]:hover{box-shadow:0 3px 0 #9e2423}.btn-red:active,input[type=reset]:active{box-shadow:0 1px 0 #9e2423}.btn-blue{background-color:#3983cd;box-shadow:0 3px 0 #265f98;text-decoration:none!important}.btn-blue,.btn-blue:link,.btn-blue:visited{color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:active,.btn-blue:hover{background-color:#2076C6;color:#FEFEFE}.btn-blue.active,.btn-blue.selected,.btn-blue:hover{box-shadow:0 3px 0 #154c80}.btn-blue:active{box-shadow:0 1px 0 #154c80}input[type=number],input[type=password],input[type=text],select,textarea{border:0 none;border-bottom:2px solid #214e7a;background-color:#303030;color:#fff;padding:6px;line-height:1em;outline:0 none!important;-moz-outline:0 none!important;font-weight:400}input[type=number]:focus,input[type=number]:hover,input[type=password]:focus,input[type=password]:hover,input[type=text]:focus,input[type=text]:hover,select:focus,select:hover,textarea:focus,textarea:hover{border-bottom-color:#2972ba}input[type=number],input[type=password],input[type=text],textarea{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;cursor:text}textarea{font-family:monospace;line-height:1.2em;display:block}form{border:0 none;margin:0;padding:0;text-decoration:none}input[type=number],input[type=password],input[type=text],label.select-wrap,select,textarea{width:250px}form .Row{vertical-align:middle;margin:14px auto;text-align:left;display:flex;flex-direction:row}form .Row:first-child{margin-top:0}form .Row:last-child{margin-bottom:0}form .Row .spacer{width:130px}@media screen and (max-width:544px){form .Row .spacer{display:none}}form .Row.buttons .button,form .Row.buttons input{margin-right:.6180469716rem}form .Row.centered{justify-content:center}form .Row.message{font-size:1em;text-shadow:1px 1px 3px black;text-align:center}form .Row.message.error{color:crimson}form .Row.message.ok{color:#0fe851}form .Row.separator{padding-top:14px;border-top:2px solid rgba(255,255,255,.1)}form .Row textarea{display:inline-block;vertical-align:top;min-height:10rem;flex-grow:1;resize:vertical}form .Row label{font-weight:700;color:#fff;text-shadow:1px 1px 3px black;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}form .Row .checkbox-wrap,form .Row label{display:inline-block;width:130px;text-align:right;padding:8px;align-self:flex-start}form .Row .checkbox-wrap input[type=checkbox]{margin:auto;width:auto;height:auto}form .Row .checkbox-wrap+label{width:250px;padding-left:0;text-align:left;cursor:pointer}@media screen and (max-width:544px){form .Row{flex-direction:column}form .Row.buttons,form .Row.centered{flex-direction:row}form .Row.buttons{justify-content:center}form .Row.buttons :last-child{margin-right:0}form .Row label{padding-left:0;text-align:left;width:auto}form .Row .checkbox-wrap{order:1;text-align:left;padding-bottom:0;border-radius:.4px;width:auto}form .Row .checkbox-wrap+label{width:auto}form .Row input[type=number],form .Row input[type=password],form .Row input[type=text],form .Row textarea{width:100%}}form span.required{color:red}.RadioGroup{display:inline-block;line-height:1.5em;vertical-align:middle}.RadioGroup label{width:auto;text-align:left;cursor:pointer;font-weight:400}.RadioGroup input[type=radio]{vertical-align:middle;margin:0 0 0 5px}@media screen and (-webkit-min-device-pixel-ratio:0){select{padding-right:18px}}select{-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;line-height:1.2em;padding-right:1em}select:-moz-focusring{color:transparent;text-shadow:0 0 0 #fff}select option{background:#303030}label.select-wrap{position:relative;display:inline!important;margin:0!important;padding:0!important;width:auto!important}label.select-wrap:after{content:'<>';font-family:Consolas,monospace;font-weight:700;color:#2972ba;top:50%;transform:translateY(-50%) rotate(90deg);right:2px;position:absolute;z-index:100;pointer-events:none}#ap-list{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:0;-moz-column-gap:0;column-gap:0;margin:0 -.2360828548rem}@media screen and (min-width:545px) and (max-width:1000px){#ap-list{-webkit-column-count:2;-moz-column-count:2;column-count:2}}@media screen and (max-width:544px){#ap-list{-webkit-column-count:1;-moz-column-count:1;column-count:1}}#ap-loader{background:rgba(255,255,255,.1);border-radius:5px;padding:.3819820591rem;margin-bottom:.3819820591rem}#ap-box{padding-bottom:.3819820591rem}#psk-modal form{display:flex;align-items:center;margin:.3819820591rem}#psk-modal form>*{margin-left:.3819820591rem;margin-right:.3819820591rem}#psk-modal form>:first-child{margin-left:0}#psk-modal form>:last-child{margin-right:0}#psk-modal form input[type=password]{min-width:5rem}.AP{-webkit-column-break-inside:avoid;page-break-inside:avoid;break-inside:avoid-column;max-width:500px;padding:.2360828548rem}.AP.selected .inner{background:#43de81!important;cursor:default;top:0!important}.AP .inner{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;border-radius:3px;color:#222;background:#afafaf;transition:background-color .5s;display:flex}.AP .inner:active{left:0;top:1px}.AP .inner:hover{background:white}.AP .inner>*{padding:.6180469716rem;white-space:nowrap;word-wrap:normal}.AP .inner .rssi{min-width:2rem;flex:0 0 15%;text-align:right}.AP .inner .rssi:after{padding-left:.090179415rem;content:'%';font-size:.8888888889em}.AP .inner .essid{flex:1 1 70%;min-width:0;text-overflow:ellipsis;overflow:hidden;font-weight:700}.AP .inner .auth{flex:0 0 15%}.page-about .Box{padding-left:1rem;padding-right:1rem}.page-about .Box a{font-weight:700}.page-about #logo{float:right;height:130px}.page-about #logo2{max-width:150px}@media screen and (min-width:545px){.mq-phone{display:none}}@media screen and (max-width:544px){.mq-tablet-min{display:none}}@media screen and (min-width:1001px){.mq-tablet-max{display:none}}@media screen and (max-width:1000px){.mq-normal-min{display:none}} \ No newline at end of file diff --git a/html_src/gulpfile.js b/html_src/gulpfile.js index ee98a02..5e490ad 100644 --- a/html_src/gulpfile.js +++ b/html_src/gulpfile.js @@ -21,18 +21,15 @@ elixir(function (mix) { // JS libs mix.scripts([ 'js-src/lib/chibi.js', - 'js-src/lib/chartist.js', - 'js-src/lib/chartist.axis-title.js', - 'js-src/lib/chartist.zoom.js', + //'js-src/lib/chartist.js', + //'js-src/lib/chartist.axis-title.js', + //'js-src/lib/chartist.zoom.js', 'js-src/lib/lodash.custom.js', 'js-src/utils.js', 'js-src/modal.js', 'js-src/notif.js', 'js-src/app.js', 'js-src/page_wifi.js', - 'js-src/page_waveform.js', - 'js-src/page_spectrogram.js', - 'js-src/page_status.js', - 'js-src/page_mon.js', + 'js-src/page_home.js', ], 'js/all.js'); }); diff --git a/html_src/js-src/lib/chibi.js b/html_src/js-src/lib/chibi.js index 0199bf3..8fccb8c 100644 --- a/html_src/js-src/lib/chibi.js +++ b/html_src/js-src/lib/chibi.js @@ -615,7 +615,7 @@ if (_.isNumber(options)) options = {timeout: options}; - var opts = Chartist.extend({}, { + var opts = _.extend({}, { nocache: true, timeout: 5000, loader: true, diff --git a/html_src/js-src/lib/lodash.custom.js b/html_src/js-src/lib/lodash.custom.js index 6e74e8e..a10ba44 100644 --- a/html_src/js-src/lib/lodash.custom.js +++ b/html_src/js-src/lib/lodash.custom.js @@ -1,7 +1,7 @@ /** * @license * lodash 4.6.1 (Custom Build) - * Build: `lodash include="range,isArray,isObject,escape,unescape,escapeRegExp,each,replace,map,isNumber,isUndefined" exports="global" -d` + * Build: `lodash include="range,isArray,isObject,escape,unescape,escapeRegExp,each,replace,map,isNumber,isUndefined,extend" exports="global" -d` * Copyright 2012-2016 The Dojo Foundation * Based on Underscore.js 1.8.3 * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors @@ -18,6 +18,9 @@ /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = '__lodash_hash_undefined__'; @@ -28,6 +31,7 @@ /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, NAN = 0 / 0; /** `Object#toString` result references. */ @@ -223,6 +227,27 @@ return set; } + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + var length = args.length; + switch (length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + /** * A specialized version of `_.forEach` for arrays without support for * iteratee shorthands. @@ -398,6 +423,23 @@ return value > -1 && value % 1 == 0 && value < length; } + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + /** * Converts `map` to an array. * @@ -469,8 +511,10 @@ /** Built-in value references. */ var Buffer = moduleExports ? root.Buffer : undefined, + Reflect = root.Reflect, Symbol = root.Symbol, Uint8Array = root.Uint8Array, + enumerate = Reflect ? Reflect.enumerate : undefined, getPrototypeOf = Object.getPrototypeOf, getOwnPropertySymbols = Object.getOwnPropertySymbols, objectCreate = Object.create, @@ -488,6 +532,9 @@ WeakMap = getNative(root, 'WeakMap'), nativeCreate = getNative(Object, 'create'); + /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */ + var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); + /** Used to lookup unminified function names. */ var realNames = {}; @@ -1372,6 +1419,31 @@ return nativeKeys(Object(object)); } + /** + * The base implementation of `_.keysIn` which doesn't skip the constructor + * property of prototypes or treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + object = object == null ? object : Object(object); + + var result = []; + for (var key in object) { + result.push(key); + } + return result; + } + + // Fallback for IE < 9 with es6-shim. + if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) { + baseKeysIn = function(object) { + return iteratorToArray(enumerate(object)); + }; + } + /** * The base implementation of `_.map` without support for iteratee shorthands. * @@ -1674,6 +1746,39 @@ return copyObject(source, getSymbols(source), object); } + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return rest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = typeof customizer == 'function' + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + /** * Creates a `baseEach` or `baseEachRight` function. * @@ -2397,6 +2502,59 @@ /*------------------------------------------------------------------------*/ + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as an array. + * + * **Note:** This method is based on the [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + switch (start) { + case 0: return func.call(this, array); + case 1: return func.call(this, args[0], array); + case 2: return func.call(this, args[0], args[1], array); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = array; + return apply(func, this, otherArgs); + }; + } + + /*------------------------------------------------------------------------*/ + /** * Performs a [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. @@ -2801,6 +2959,43 @@ return value === undefined; } + /** + * Converts `value` to an integer. + * + * **Note:** This function is loosely based on [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3'); + * // => 3 + */ + function toInteger(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + var remainder = value % 1; + return value === value ? (remainder ? value - remainder : value) : 0; + } + /** * Converts `value` to a number. * @@ -2875,6 +3070,45 @@ /*------------------------------------------------------------------------*/ + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * function Bar() { + * this.d = 4; + * } + * + * Foo.prototype.c = 3; + * Bar.prototype.e = 5; + * + * _.assignIn({ 'a': 1 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 } + */ + var assignIn = createAssigner(function(object, source) { + if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { + copyObject(source, keysIn(source), object); + return; + } + for (var key in source) { + assignValue(object, key, source[key]); + } + }); + /** * Gets the value at `path` of `object`. If the resolved value is * `undefined` the `defaultValue` is used in its place. @@ -2980,6 +3214,48 @@ return result; } + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + var index = -1, + isProto = isPrototype(object), + props = baseKeysIn(object), + propsLength = props.length, + indexes = indexKeys(object), + skipIndexes = !!indexes, + result = indexes || [], + length = result.length; + + while (++index < propsLength) { + var key = props[index]; + if (!(skipIndexes && (key == 'length' || isIndex(key, length))) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + /** * Creates an array of own enumerable key-value pairs for `object` which * can be consumed by `_.fromPairs`. @@ -3279,14 +3555,20 @@ Stack.prototype.set = stackSet; // Add functions that return wrapped values when chaining. + lodash.assignIn = assignIn; lodash.constant = constant; lodash.iteratee = iteratee; lodash.keys = keys; + lodash.keysIn = keysIn; lodash.map = map; lodash.property = property; lodash.range = range; + lodash.rest = rest; lodash.toPairs = toPairs; + // Add aliases. + lodash.extend = assignIn; + /*------------------------------------------------------------------------*/ // Add functions that return unwrapped values when chaining. @@ -3314,6 +3596,7 @@ lodash.isUndefined = isUndefined; lodash.last = last; lodash.replace = replace; + lodash.toInteger = toInteger; lodash.toNumber = toNumber; lodash.toString = toString; lodash.unescape = unescape; diff --git a/html_src/js-src/page_home.js b/html_src/js-src/page_home.js new file mode 100644 index 0000000..5cd06b2 --- /dev/null +++ b/html_src/js-src/page_home.js @@ -0,0 +1,11 @@ +/** Wifi page */ +var page_home = (function () { + var home = {}; + + /** Set up the Home page */ + home.init = function () { + // + }; + + return home; +})(); diff --git a/html_src/js-src/page_mon.js b/html_src/js-src/page_mon.js deleted file mode 100644 index 6242336..0000000 --- a/html_src/js-src/page_mon.js +++ /dev/null @@ -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; -})(); diff --git a/html_src/js-src/page_spectrogram.js b/html_src/js-src/page_spectrogram.js deleted file mode 100644 index 6d2203b..0000000 --- a/html_src/js-src/page_spectrogram.js +++ /dev/null @@ -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= 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; -})(); diff --git a/html_src/js-src/page_status.js b/html_src/js-src/page_status.js deleted file mode 100644 index f782549..0000000 --- a/html_src/js-src/page_status.js +++ /dev/null @@ -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; -})(); diff --git a/html_src/js-src/page_waveform.js b/html_src/js-src/page_waveform.js deleted file mode 100644 index 6f64346..0000000 --- a/html_src/js-src/page_waveform.js +++ /dev/null @@ -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; -})(); diff --git a/html_src/js/all.js b/html_src/js/all.js index 320e41c..2fff11b 100644 --- a/html_src/js/all.js +++ b/html_src/js/all.js @@ -1,3 +1 @@ -function bool(t){return 1===t||"1"===t||t===!0||"true"===t}function numfmt(t,e){var n=Math.pow(10,e);return Math.round(t*n)/n}function estimateLoadTime(t,e){return 1e3/t*e+1500}function msNow(){return+new Date}function msElapsed(t){return msNow()-t}function copyToClipboard(t){if(!document.execCommand)return!1;var e="_hiddenCopyText_";if(n=document.getElementById(e),!n){var n=document.createElement("textarea");n.style.position="absolute",n.style.left="-9999px",n.style.top="0",n.id=e,document.body.appendChild(n)}n.textContent=t;var r=document.activeElement;n.focus(),n.setSelectionRange(0,n.value.length);var i;try{i=document.execCommand("copy")}catch(a){i=!1}return r&&"function"==typeof r.focus&&r.focus(),n.textContent="",i}function errorMsg(t,e){$("#notif").addClass("error"),notify.show(t,e||3e3)}function infoMsg(t,e){$("#notif").removeClass("error"),notify.show(t,e||3e3)}!function(){"use strict";function t(){var t;for(p=!0,t=0;t=0;n-=1)t(e[n])}function r(t){return t.replace(/-\w/g,function(t){return t.charAt(1).toUpperCase()})}function i(t,e){return t.currentStyle?t.currentStyle[r(e)]:g.getComputedStyle?g.getComputedStyle(t,null).getPropertyValue(e):null}function a(t,e){return encodeURIComponent(t).replace(/%20/g,"+")+"="+encodeURIComponent(e).replace(/%20/g,"+")}function o(t,e,n){try{t.style[r(e)]=n}catch(i){}}function s(t){t.style.display="","none"===i(t,"display")&&(t.style.display="block")}function u(t){var e,r,i,o="";if(t.constructor===Object){for(e in t)if(t.hasOwnProperty(e))if(t[e].constructor===Array)for(r=0;r0&&(o+="&"+a(e.name,e.value));break;case"select-multiple":for(i=0;i0?o.substring(1):""}function c(t,e,r){var i,a,o,s=!1;return t&&(i=t.split(/\s+/),n(function(t){for(o=0;o0?y[0].className.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"").replace(/\s+/," "):void 0},e.setClass=function(t){return(t||""===t)&&n(function(e){e.className=t},y),e},e.addClass=function(t){return t&&n(function(e){e.className+=" "+t},y),e},e.removeClass=function(t){return c(t,"remove",y),e},e.toggleClass=function(t){return c(t,"toggle",y),e},e.hasClass=function(t){return c(t,"has",y)},e.html=function(t){return t||""===t?(n(function(e){e.innerHTML=t},y),e):y[0]?y[0].innerHTML:void 0},e.htmlBefore=function(t){return l(t,"before",y),e},e.htmlAfter=function(t){return l(t,"after",y),e},e.htmlAppend=function(t){return l(t,"append",y),e},e.htmlPrepend=function(t){return l(t,"prepend",y),e},e.attr=function(t,r){if(t){if(t=t.toLowerCase(),"undefined"!=typeof r)return n(function(e){"style"===t?e.style.cssText=r:"class"===t?e.className=r:e.setAttribute(t,r)},y),e;if(y[0])if("style"===t){if(y[0].style.cssText)return y[0].style.cssText}else if("class"===t){if(y[0].className)return y[0].className}else if(y[0].getAttribute(t))return y[0].getAttribute(t)}},e.data=function(t,n){return t?e.attr("data-"+t,n):void 0},e.val=function(t){var r,i,a;if(!_.isUndefined(t))return n(function(e){switch(e.nodeName){case"SELECT":for(("string"==typeof t||"number"==typeof t)&&(t=[t]),i=0;i1?r:r[0];case"INPUT":case"TEXTAREA":case"BUTTON":return y[0].value}},e.checked=function(t){return"boolean"==typeof t?(n(function(e){"INPUT"!==e.nodeName||"checkbox"!==e.type&&"radio"!==e.type||(e.checked=t)},y),e):!y[0]||"INPUT"!==y[0].nodeName||"checkbox"!==y[0].type&&"radio"!==y[0].type?void 0:!!y[0].checked},e.on=function(r,i){return(t===g||t===v)&&(y=[t]),n(function(t){v.addEventListener?t.addEventListener(r,i,!1):v.attachEvent&&(t[r+i]=function(){return i.apply(t,arguments)},t.attachEvent("on"+r,t[r+i]))},y),e},e.off=function(r,i){return(t===g||t===v)&&(y=[t]),n(function(t){v.addEventListener?t.removeEventListener(r,i,!1):v.attachEvent&&(t.detachEvent("on"+r,t[r+i]),t[r+i]=null)},y),e},e.ajax=function(t,e,n,r){var i,a,o=u(y),s=e?e.toUpperCase():"GET";_.isNumber(r)&&(r={timeout:r});var c=Chartist.extend({},{nocache:!0,timeout:5e3,loader:!0},r);if(o&&"GET"===s&&(t+=-1===t.indexOf("?")?"?"+o:"&"+o,o=null),i=new XMLHttpRequest){if(c.nocache){var l=(+new Date).toString(36);t+=(-1===t.indexOf("?")?"?":"&")+"_="+l}c.loader&&$("#loader").addClass("show"),i.open(s,t,!0),i.timeout=c.timeout,a=setTimeout(function(){errorMsg("XHR timed out."),i.abort(),c.loader&&$("#loader").removeClass("show")},c.timeout+10),i.onreadystatechange=function(){4===i.readyState&&(c.loader&&$("#loader").removeClass("show"),n&&0!=i.status&&n(i.responseText,i.status),clearTimeout(a))},i.setRequestHeader("X-Requested-With","XMLHttpRequest"),"POST"===s&&i.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),i.send(o)}return i},e.get=function(t,n,r){return e.ajax(t,"get",n,r)},e.post=function(t,n,r){return e.ajax(t,"post",n,r)},e}var f=[],d=[],p=!1,m=!1,v=document,g=window;v.addEventListener?(v.addEventListener("DOMContentLoaded",t,!1),g.addEventListener("load",e,!1)):v.attachEvent?(v.attachEvent("onreadystatechange",t),g.attachEvent("onload",e)):g.onload=e,g.$=h}(),function(t,e){t.Chartist=e()}(this,function(){var t={version:"0.9.7"};return function(t,e,n){"use strict";n.namespaces={svg:"http://www.w3.org/2000/svg",xmlns:"http://www.w3.org/2000/xmlns/",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",ct:"http://gionkunz.github.com/chartist-js/ct"},n.noop=function(t){return t},n.alphaNumerate=function(t){return String.fromCharCode(97+t%26)},n.extend=function(t){t=t||{};var e=Array.prototype.slice.call(arguments,1);return e.forEach(function(e){for(var r in e)"object"!=typeof e[r]||null===e[r]||e[r]instanceof Array?t[r]=e[r]:t[r]=n.extend({},t[r],e[r])}),t},n.replaceAll=function(t,e,n){return t.replace(new RegExp(e,"g"),n)},n.ensureUnit=function(t,e){return"number"==typeof t&&(t+=e),t},n.quantity=function(t){if("string"==typeof t){var e=/^(\d+)\s*(.*)$/g.exec(t);return{value:+e[1],unit:e[2]||void 0}}return{value:t}},n.querySelector=function(t){return t instanceof Node?t:e.querySelector(t)},n.times=function(t){return Array.apply(null,new Array(t))},n.sum=function(t,e){return t+(e?e:0)},n.mapMultiply=function(t){return function(e){return e*t}},n.mapAdd=function(t){return function(e){return e+t}},n.serialMap=function(t,e){var r=[],i=Math.max.apply(null,t.map(function(t){return t.length}));return n.times(i).forEach(function(n,i){var a=t.map(function(t){return t[i]});r[i]=e.apply(null,a)}),r},n.roundWithPrecision=function(t,e){var r=Math.pow(10,e||n.precision);return Math.round(t*r)/r},n.precision=8,n.serialize=function(t){return null===t||void 0===t?t:("number"==typeof t?t=""+t:"object"==typeof t&&(t=JSON.stringify({data:t})),_.escape(t))},n.deserialize=function(t){if("string"!=typeof t)return t;t=_.unescape(t);try{t=JSON.parse(t),t=void 0!==t.data?t.data:t}catch(e){}return t},n.createSvg=function(t,e,r,i){var a;return e=e||"100%",r=r||"100%",Array.prototype.slice.call(t.querySelectorAll("svg")).filter(function(t){return t.getAttributeNS(n.namespaces.xmlns,"ct")}).forEach(function(e){t.removeChild(e)}),a=new n.Svg("svg").attr({width:e,height:r}).addClass(i).attr({style:"width: "+e+"; height: "+r+";"}),t.appendChild(a._node),a},n.normalizeData=function(t){if(t=t||{series:[],labels:[]},t.series=t.series||[],t.labels=t.labels||[],t.series.length>0&&0===t.labels.length){var e,r=n.getDataArray(t);e=r.every(function(t){return t instanceof Array})?Math.max.apply(null,r.map(function(t){return t.length})):r.length,t.labels=n.times(e).map(function(){return""})}return t},n.reverseData=function(t){t.labels.reverse(),t.series.reverse();for(var e=0;ea.high&&(a.high=n),s&&n0?a.low=0:(a.high=1,a.low=0)),a},n.isNum=function(t){return!isNaN(t)&&isFinite(t)},n.isFalseyButZero=function(t){return!t&&0!==t},n.getNumberOrUndefined=function(t){return isNaN(+t)?void 0:+t},n.getMultiValue=function(t,e){return n.isNum(t)?+t:t?t[e||"y"]||0:0},n.rho=function(t){function e(t,n){return t%n===0?n:e(n,t%n)}function n(t){return t*t+1}if(1===t)return t;var r,i=2,a=2;if(t%2===0)return 2;do i=n(i)%t,a=n(n(a))%t,r=e(Math.abs(i-a),t);while(1===r);return r},n.getBounds=function(t,e,r,i){var a,o,s,u=0,c={high:e.high,low:e.low};c.valueRange=c.high-c.low,c.oom=n.orderOfMagnitude(c.valueRange),c.step=Math.pow(10,c.oom),c.min=Math.floor(c.low/c.step)*c.step,c.max=Math.ceil(c.high/c.step)*c.step,c.range=c.max-c.min,c.numberOfSteps=Math.round(c.range/c.step);var l=n.projectLength(t,c.step,c),h=r>l,f=i?n.rho(c.range):0;if(i&&n.projectLength(t,1,c)>=r)c.step=1;else if(i&&f=r)c.step=f;else for(;;){if(h&&n.projectLength(t,c.step,c)<=r)c.step*=2;else{if(h||!(n.projectLength(t,c.step/2,c)>=r))break;if(c.step/=2,i&&c.step%1!==0){c.step*=2;break}}if(u++>1e3)throw new Error("Exceeded maximum number of iterations while optimizing scale step!")}for(o=c.min,s=c.max;o+c.step<=c.low;)o+=c.step;for(;s-c.step>=c.high;)s-=c.step;for(c.min=o,c.max=s,c.range=c.max-c.min,c.values=[],a=c.min;a<=c.max;a+=c.step)c.values.push(n.roundWithPrecision(a));return c},n.createChartRect=function(t,e,r){var i=!(!e.axisX&&!e.axisY),a=i?e.axisY.offset:0,o=i?e.axisX.offset:0,s=t.width()||n.quantity(e.width).value||0,u=t.height()||n.quantity(e.height).value||0,c=n.normalizePadding(e.chartPadding,r);s=Math.max(s,a+c.left+c.right),u=Math.max(u,o+c.top+c.bottom);var l={padding:c,width:function(){return this.x2-this.x1},height:function(){return this.y1-this.y2}};return i?("start"===e.axisX.position?(l.y2=c.top+o,l.y1=Math.max(u-c.bottom,l.y2+1)):(l.y2=c.top,l.y1=Math.max(u-c.bottom-o,l.y2+1)),"start"===e.axisY.position?(l.x1=c.left+a,l.x2=Math.max(s-c.right,l.x1+1)):(l.x1=c.left,l.x2=Math.max(s-c.right-a,l.x1+1))):(l.x1=c.left,l.x2=Math.max(s-c.right,l.x1+1),l.y2=c.top,l.y1=Math.max(u-c.bottom,l.y2+1)),l},n.createGrid=function(t,e,r,i,a,o,s,u){var c={};c[r.units.pos+"1"]=Math.round(t)+.5,c[r.units.pos+"2"]=Math.round(t)+.5,c[r.counterUnits.pos+"1"]=i,c[r.counterUnits.pos+"2"]=i+a;var l=o.elem("line",c,s.join(" "));u.emit("draw",n.extend({type:"grid",axis:r,index:e,group:o,element:l},c))},n.createLabel=function(t,e,r,i,a,o,s,u,c,l,h){var f,d={};d[a.units.pos]=t+s[a.units.pos],d[a.counterUnits.pos]=s[a.counterUnits.pos],d[a.units.len]=e,d[a.counterUnits.len]=o-10;var p=i[r];if(_.isNumber(p)&&(p=n.roundWithPrecision(p,2)),l){var m=''+p+"";f=u.foreignObject(m,n.extend({style:"overflow: visible;"},d))}else f=u.elem("text",d,c.join(" ")).text(p);h.emit("draw",n.extend({type:"label",axis:a,index:r,group:u,element:f,text:p},d))},n.getSeriesOption=function(t,e,n){if(t.name&&e.series&&e.series[t.name]){var r=e.series[t.name];return r.hasOwnProperty(n)?r[n]:e[n]}return e[n]},n.optionsProvider=function(e,r,i){function a(e){var a=s;if(s=n.extend({},c),r)for(u=0;u=2&&e[a]<=e[a-2]?i=!0:(i&&(r.push({pathCoordinates:[],valueData:[]}),i=!1),r[r.length-1].pathCoordinates.push(e[a],e[a+1]),r[r.length-1].valueData.push(n[a/2]));return r}var r={fillHoles:!1};return t=n.extend({},r,t),function i(t,r){var a=e(t,r);if(a.length){if(a.length>1){var o=[];return a.forEach(function(t){o.push(i(t.pathCoordinates,t.valueData))}),n.Svg.Path.join(o)}if(t=a[0].pathCoordinates,r=a[0].valueData,t.length<=4)return n.Interpolation.none()(t,r);var s,u,c=[],l=[],h=t.length/2,f=[],d=[],p=[],m=[];for(s=0;h>s;s++)c[s]=t[2*s],l[s]=t[2*s+1];for(s=0;h-1>s;s++)p[s]=l[s+1]-l[s],m[s]=c[s+1]-c[s],d[s]=p[s]/m[s];for(f[0]=d[0],f[h-1]=d[h-2],s=1;h-1>s;s++)0===d[s]||0===d[s-1]||d[s-1]>0!=d[s]>0?f[s]=0:(f[s]=3*(m[s-1]+m[s])/((2*m[s]+m[s-1])/d[s-1]+(m[s]+2*m[s-1])/d[s]),isFinite(f[s])||(f[s]=0));for(u=(new n.Svg.Path).move(c[0],l[0],!1,r[0]),s=0;h-1>s;s++)u.curve(c[s]+m[s]/3,l[s]+f[s]*m[s]/3,c[s+1]-m[s]/3,l[s+1]-f[s+1]*m[s]/3,c[s+1],l[s+1],!1,r[s+1]);return u}return n.Interpolation.none()([])}},n.Interpolation.step=function(t){var e={postpone:!0,fillHoles:!1};return t=n.extend({},e,t),function(e,r){for(var i,a,o,s=new n.Svg.Path,u=0;u1}).map(function(t){var e=t.pathElements[0],n=t.pathElements[t.pathElements.length-1];return t.clone(!0).position(0).remove(1).move(e.x,g).line(e.x,e.y).position(t.pathElements.length+1).line(n.x,g)}).forEach(function(n){var s=u.elem("path",{d:n.stringify()},t.classNames.area,!0);this.eventEmitter.emit("draw",{type:"area",values:e.normalized[o],path:n.clone(),series:a,seriesIndex:o,axisX:r,axisY:i,chartRect:c,index:o,group:u,element:s})}.bind(this))}}.bind(this)),this.eventEmitter.emit("created",{bounds:i.bounds,chartRect:c,axisX:r,axisY:i,svg:this.svg,options:t})}function i(t,e,r,i){n.Line["super"].constructor.call(this,t,e,a,n.extend({},a,r),i)}var a={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,type:void 0},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,type:void 0,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,showLine:!0,showPoint:!0,showArea:!1,areaBase:0,lineSmooth:!0,low:void 0,high:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},fullWidth:!1,reverseData:!1,classNames:{chart:"ct-chart-line",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",line:"ct-line",point:"ct-point",area:"ct-area",grid:"ct-grid",gridGroup:"ct-grids",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};n.Line=n.Base.extend({constructor:i,createChart:r})}(window,document,t),function(t,e,n){"use strict";function r(t){this.data=n.normalizeData(this.data);var e,r={raw:this.data,normalized:t.distributeSeries?n.getDataArray(this.data,t.reverseData,t.horizontalBars?"x":"y").map(function(t){return[t]}):n.getDataArray(this.data,t.reverseData,t.horizontalBars?"x":"y")};this.svg=n.createSvg(this.container,t.width,t.height,t.classNames.chart+(t.horizontalBars?" "+t.classNames.horizontalBars:""));var i=this.svg.elem("g").addClass(t.classNames.gridGroup),o=this.svg.elem("g"),s=this.svg.elem("g").addClass(t.classNames.labelGroup);if(t.stackBars&&0!==r.normalized.length){var u=n.serialMap(r.normalized,function(){return Array.prototype.slice.call(arguments).map(function(t){return t}).reduce(function(t,e){return{x:t.x+(e&&e.x)||0,y:t.y+(e&&e.y)||0}},{x:0,y:0})});e=n.getHighLow([u],n.extend({},t,{referenceValue:0}),t.horizontalBars?"x":"y")}else e=n.getHighLow(r.normalized,n.extend({},t,{referenceValue:0}),t.horizontalBars?"x":"y");e.high=+t.high||(0===t.high?0:e.high),e.low=+t.low||(0===t.low?0:e.low);var c,l,h,f,d,p=n.createChartRect(this.svg,t,a.padding);l=t.distributeSeries&&t.stackBars?r.raw.labels.slice(0,1):r.raw.labels,t.horizontalBars?(c=f=void 0===t.axisX.type?new n.AutoScaleAxis(n.Axis.units.x,r,p,n.extend({},t.axisX,{highLow:e,referenceValue:0})):t.axisX.type.call(n,n.Axis.units.x,r,p,n.extend({},t.axisX,{highLow:e,referenceValue:0})),h=d=void 0===t.axisY.type?new n.StepAxis(n.Axis.units.y,r,p,{ticks:l}):t.axisY.type.call(n,n.Axis.units.y,r,p,t.axisY)):(h=f=void 0===t.axisX.type?new n.StepAxis(n.Axis.units.x,r,p,{ticks:l}):t.axisX.type.call(n,n.Axis.units.x,r,p,t.axisX),c=d=void 0===t.axisY.type?new n.AutoScaleAxis(n.Axis.units.y,r,p,n.extend({},t.axisY,{highLow:e,referenceValue:0})):t.axisY.type.call(n,n.Axis.units.y,r,p,n.extend({},t.axisY,{highLow:e,referenceValue:0})));var m=t.horizontalBars?p.x1+c.projectValue(0):p.y1-c.projectValue(0),v=[];h.createGridAndLabels(i,s,this.supportsForeignObject,t,this.eventEmitter),c.createGridAndLabels(i,s,this.supportsForeignObject,t,this.eventEmitter),r.raw.series.forEach(function(e,i){var a,s,u=i-(r.raw.series.length-1)/2;a=t.distributeSeries&&!t.stackBars?h.axisLength/r.normalized.length/2:t.distributeSeries&&t.stackBars?h.axisLength/2:h.axisLength/r.normalized[i].length/2,s=o.elem("g"),s.attr({"ct:series-name":e.name,"ct:meta":n.serialize(e.meta)}),s.addClass([t.classNames.series,e.className||t.classNames.series+"-"+n.alphaNumerate(i)].join(" ")),r.normalized[i].forEach(function(o,l){var g,x,y,b;if(b=t.distributeSeries&&!t.stackBars?i:t.distributeSeries&&t.stackBars?0:l,g=t.horizontalBars?{x:p.x1+c.projectValue(o&&o.x?o.x:0,l,r.normalized[i]),y:p.y1-h.projectValue(o&&o.y?o.y:0,b,r.normalized[i])}:{x:p.x1+h.projectValue(o&&o.x?o.x:0,b,r.normalized[i]),y:p.y1-c.projectValue(o&&o.y?o.y:0,l,r.normalized[i])},h instanceof n.StepAxis&&(h.options.stretch||(g[h.units.pos]+=a*(t.horizontalBars?-1:1)),g[h.units.pos]+=t.stackBars||t.distributeSeries?0:u*t.seriesBarDistance*(t.horizontalBars?-1:1)),y=v[l]||m,v[l]=y-(m-g[h.counterUnits.pos]),void 0!==o){var w={};w[h.units.pos+"1"]=g[h.units.pos],w[h.units.pos+"2"]=g[h.units.pos],!t.stackBars||"accumulate"!==t.stackMode&&t.stackMode?(w[h.counterUnits.pos+"1"]=m,w[h.counterUnits.pos+"2"]=g[h.counterUnits.pos]):(w[h.counterUnits.pos+"1"]=y,w[h.counterUnits.pos+"2"]=v[l]),w.x1=Math.min(Math.max(w.x1,p.x1),p.x2),w.x2=Math.min(Math.max(w.x2,p.x1),p.x2),w.y1=Math.min(Math.max(w.y1,p.y2),p.y1),w.y2=Math.min(Math.max(w.y2,p.y2),p.y1),x=s.elem("line",w,t.classNames.bar).attr({"ct:value":[o.x,o.y].filter(n.isNum).join(","),"ct:meta":n.getMetaData(e,l)}),this.eventEmitter.emit("draw",n.extend({type:"bar",value:o,index:l,meta:n.getMetaData(e,l),series:e,seriesIndex:i,axisX:f,axisY:d,chartRect:p,group:s,element:x},w))}}.bind(this))}.bind(this)),this.eventEmitter.emit("created",{bounds:c.bounds,chartRect:p,axisX:f,axisY:d,svg:this.svg,options:t})}function i(t,e,r,i){n.Bar["super"].constructor.call(this,t,e,a,n.extend({},a,r),i)}var a={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,scaleMinSpace:30,onlyInteger:!1},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:n.noop,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,high:void 0,low:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},seriesBarDistance:15,stackBars:!1,stackMode:"accumulate",horizontalBars:!1,distributeSeries:!1,reverseData:!1,classNames:{chart:"ct-chart-bar",horizontalBars:"ct-horizontal-bars",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",bar:"ct-bar",grid:"ct-grid",gridGroup:"ct-grids",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};n.Bar=n.Base.extend({constructor:i,createChart:r})}(window,document,t),t}),function(t,e){t["Chartist.plugins.ctAxisTitle"]=e()}(this,function(){return function(t,e,n){"use strict";var r={axisTitle:"",axisClass:"ct-axis-title",offset:{x:0,y:0},textAnchor:"middle",flipText:!1},i={axisX:r,axisY:r};n.plugins=n.plugins||{},n.plugins.ctAxisTitle=function(t){return t=n.extend({},i,t),function(e){e.on("created",function(e){var r,i,a;if(t.axisX.axisTitle&&e.axisX&&(r=e.axisX.axisLength/2+e.options.axisY.offset+e.options.chartPadding.left,i=e.options.chartPadding.top,"end"===e.options.axisY.position&&(r-=e.options.axisY.offset),"end"===e.options.axisX.position&&(i+=e.axisY.axisLength),a=new n.Svg("text"),a.addClass(t.axisX.axisClass),a.text(t.axisX.axisTitle),a.attr({x:r+t.axisX.offset.x,y:i+t.axisX.offset.y,"text-anchor":t.axisX.textAnchor}),e.svg.append(a,!0)),t.axisY.axisTitle&&e.axisY){r=0,i=e.axisY.axisLength/2+e.options.chartPadding.top,"start"===e.options.axisX.position&&(i+=e.options.axisX.offset),"end"===e.options.axisY.position&&(r=e.axisX.axisLength);var o="rotate("+(t.axisY.flipText?-90:90)+", "+r+", "+i+")";a=new n.Svg("text"),a.addClass(t.axisY.axisClass),a.text(t.axisY.axisTitle),a.attr({x:r+t.axisY.offset.x,y:i+t.axisY.offset.y,transform:o,"text-anchor":t.axisY.textAnchor}),e.svg.append(a,!0)}})}}}(window,document,Chartist),Chartist.plugins.ctAxisTitle}),function(t,e){t["Chartist.plugins.zoom"]=e()}(this,function(){return function(t,e,n){"use strict";function r(t){t.attr({style:"display:none"})}function i(t){t.attr({style:"display:block"})}function a(t,e){var n=t.x,r=t.y,i=e.x-n,a=e.y-r;return 0>i&&(i=-i,n=e.x),0>a&&(a=-a,r=e.y),{x:n,y:r,width:i,height:a}}function o(t,e){return s(t.clientX,t.clientY,e)}function s(t,e,n){var r="svg"===n.tagName?n:n.ownerSVGElement,i=r.getScreenCTM(),a=r.createSVGPoint();return a.x=t,a.y=e,a=a.matrixTransform(i.inverse()),a||{x:0,y:0}}function u(t,e){var n=e.bounds.max,r=e.bounds.min;if(e.scale&&"log"===e.scale.type){var i=e.scale.base;return Math.pow(i,t*c(n/r,i)/e.axisLength)*r}return t*e.bounds.range/e.axisLength+r}function c(t,e){return Math.log(t)/Math.log(e)}var l={};n.plugins=n.plugins||{},n.plugins.zoom=function(t){return t=n.extend({},l,t),function(e){function s(t){var e=o(t,b);return e.id=t.identifier,e}function c(t){for(var e=0;e1&&(y.attr(a(M[0],M[1])),i(y))}function h(t){for(var e=t.changedTouches,n=0;n1&&(y.attr(a(M[0],M[1])),i(y),t.preventDefault())}function f(t){d(t.changedTouches)}function d(t){for(var e=0;e=0&&M.splice(n,1)}}function p(t){M.length>1&&g(a(M[0],M[1])),d(t.changedTouches),r(y)}function m(t){0===t.button&&(A=o(t,b),y.attr(a(A,A)),i(y),t.preventDefault())}function v(e){if(0===e.button){var n=a(A,o(e,b));g(n),A=null,r(y),e.preventDefault()}else t.resetOnRightMouseBtn&&2===e.button&&(O(),e.preventDefault())}function g(t){if(t.width>5&&t.height>5){var n=t.x-S.x1,r=n+t.width,i=S.y1-t.y,a=i-t.height,o=u(n,w),s=u(r,w),c=u(a,E),l=u(i,E),h=e.options.explicitBounds;_.isUndefined(h)||(_.isUndefined(h.xLow)||(o=Math.max(h.xLow,o)),_.isUndefined(h.xHigh)||(s=Math.min(h.xHigh,s)),_.isUndefined(h.yLow)||(c=Math.max(h.yLow,c)),_.isUndefined(h.yHigh)||(l=Math.min(h.yHigh,l))),e.options.axisX.highLow={low:o,high:s},e.options.axisY.highLow={low:c,high:l},e.update(e.data,e.options),C&&C(e,O)}}function x(t){if(A){var e=o(t,b);y.attr(a(A,e)),t.preventDefault()}}if(e instanceof n.Line){var y,b,w,E,S,A,C=t.onZoom,M=[];e.on("draw",function(t){var e=t.type;("line"===e||"bar"===e||"area"===e||"point"===e)&&t.element.attr({"clip-path":"url(#zoom-mask)"})}),e.on("created",function(t){w=t.axisX,E=t.axisY,S=t.chartRect,b=t.svg._node,y=t.svg.elem("rect",{x:10,y:10,width:100,height:100},"ct-zoom-rect"),r(y);var e=t.svg.querySelector("defs")||t.svg.elem("defs"),n=S.width(),i=S.height();e.elem("clipPath",{id:"zoom-mask"}).elem("rect",{x:S.x1,y:S.y2,width:n,height:i,fill:"white"}),b.addEventListener("mousedown",m),b.addEventListener("mouseup",v),b.addEventListener("mousemove",x),b.addEventListener("touchstart",l),b.addEventListener("touchmove",h),b.addEventListener("touchend",p),b.addEventListener("touchcancel",f)});var O=function(){e.options.axisX.highLow=null,e.options.axisY.highLow=null,e.update(e.data,e.options)}}}}}(window,document,Chartist),Chartist.plugins.zoom}),function(){function t(t,e){return t.set(e[0],e[1]),t}function e(t,e){return t.add(e),t}function n(t,e){for(var n=-1,r=t.length;++n-1&&t%1==0&&e>t}function f(t){var e=-1,n=Array(t.size);return t.forEach(function(t,r){n[++e]=[r,t]}),n}function d(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=t}),n}function p(t){return gn[t]}function m(){}function v(){}function g(t,e){return y(t,e)&&delete t[e]}function x(t,e){if(Gn){var n=t[e];return n===ye?ve:n}return Nn.call(t,e)?t[e]:ve}function y(t,e){return Gn?t[e]!==ve:Nn.call(t,e)}function b(t,e,n){t[e]=Gn&&n===ve?ye:n}function w(t){var e=-1,n=t?t.length:0;for(this.clear();++en)return!1;var r=t.length-1;return n==r?t.pop():Xn.call(t,n,1),!0}function T(t,e){var n=P(t,e);return 0>n?ve:t[n][1]}function I(t,e){return P(t,e)>-1}function P(t,e){for(var n=t.length;n--;)if(Yt(t[n][0],e))return n;return-1}function z(t,e,n){var r=P(t,e);0>r?t.push([e,n]):t[r][1]=n}function B(t,e,n){var r=t[e];Nn.call(t,e)&&Yt(r,n)&&(n!==ve||e in t)||(t[e]=n)}function R(t,e){return t&&pt(e,oe(e),t)}function U(t){return"function"==typeof t?t:de}function X(t){return ar(t)?t:Bt(t)}function Y(t,e,r,i,a,o,s){var u;if(i&&(u=o?i(t,a,o,s):i(t)),u!==ve)return u;if(!Gt(t))return t;var c=ar(t);if(c){if(u=Ot(t),!e)return dt(t,u)}else{var h=_t(t),f=h==$e||h==Ne;if(or(t))return ot(t,e);if(h==Te||h==Ce||f&&!o){if(l(t))return o?t:{};if(u=Lt(f?{}:t),!e)return u=R(u,t),r?vt(t,u):u}else{if(!mn[h])return o?t:{};u=$t(t,h,e)}}s||(s=new M);var d=s.get(t);return d?d:(s.set(t,u),(c?n:D)(t,function(n,a){B(u,a,Y(n,e,r,i,a,t,s))}),r&&!c?vt(t,u):u)}function q(t){return Gt(t)?Rn(t):{}}function D(t,e){return t&&nr(t,e,oe)}function F(t,e){e=kt(e,t)?[e+""]:X(e);for(var n=0,r=e.length;null!=t&&r>n;)t=t[e[n++]];return n&&n==r?t:ve}function H(t,e){return Nn.call(t,e)||"object"==typeof t&&e in t&&null===zn(t)}function V(t,e){return e in Object(t)}function G(t,e,n,r,i){return t===e?!0:null==t||null==e||!Gt(t)&&!Wt(e)?t!==t&&e!==e:W(t,e,G,n,r,i)}function W(t,e,n,r,i,a){var o=ar(t),s=ar(e),u=_e,c=_e;o||(u=_t(t),u=u==Ce?Te:u),s||(c=_t(e),c=c==Ce?Te:c);var h=u==Te&&!l(t),f=c==Te&&!l(e),d=u==c;if(d&&!h)return a||(a=new M),o||te(t)?bt(t,e,n,r,i,a):wt(t,e,u,n,r,i,a);if(!(i&we)){var p=h&&Nn.call(t,"__wrapped__"),m=f&&Nn.call(e,"__wrapped__");if(p||m)return a||(a=new M),n(p?t.value():t,m?e.value():e,r,i,a)}return d?(a||(a=new M),Et(t,e,n,r,i,a)):!1}function Q(t,e,n,r){var i=n.length,a=i,o=!r;if(null==t)return!a;for(t=Object(t);i--;){var s=n[i];if(o&&s[2]?s[1]!==t[s[0]]:!(s[0]in t))return!1}for(;++ie&&(e=-e>i?0:i+e),n=n>i?i:n,0>n&&(n+=i),i=e>n?0:n-e>>>0,e>>>=0;for(var a=Array(i);++re?1:-1:ne(r)||0,it(e,n,r,t)}}function bt(t,e,n,r,i,o){var s=-1,u=i&we,c=i&be,l=t.length,h=e.length;if(l!=h&&!(u&&h>l))return!1;var f=o.get(t);if(f)return f==e;var d=!0;for(o.set(t,e);++s-1&&t%1==0&&Se>=t}function Gt(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function Wt(t){return!!t&&"object"==typeof t}function Qt(t){return null==t?!1:Ht(t)?kn.test($n.call(t)):Wt(t)&&(l(t)?kn:hn).test(t)}function Zt(t){return"number"==typeof t||Wt(t)&&jn.call(t)==ke}function Jt(t){return"string"==typeof t||!ar(t)&&Wt(t)&&jn.call(t)==ze}function Kt(t){return"symbol"==typeof t||Wt(t)&&jn.call(t)==Be}function te(t){return Wt(t)&&Vt(t.length)&&!!pn[jn.call(t)]}function ee(t){return t===ve}function ne(t){if(Gt(t)){var e=Ht(t.valueOf)?t.valueOf():t;t=Gt(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(on,"");var n=ln.test(t);return n||fn.test(t)?yn(t.slice(2),n?2:8):cn.test(t)?Ae:+t}function re(t){if("string"==typeof t)return t;if(null==t)return"";if(Kt(t))return tr?tr.call(t):"";var e=t+"";return"0"==e&&1/t==-Ee?"-0":e}function ie(t,e,n){var r=null==t?ve:F(t,e);return r===ve?n:r}function ae(t,e){return Mt(t,e,V)}function oe(t){var e=It(t);if(!e&&!Dt(t))return J(t);var n=Nt(t),r=!!n,i=n||[],a=i.length;for(var o in t)!H(t,o)||r&&("length"==o||h(o,a))||e&&"constructor"==o||i.push(o);return i}function se(t){return s(t,oe(t))}function ue(t){return t=re(t),t&&Ke.test(t)?t.replace(Ze,c):t}function ce(t){return t=re(t),t&&an.test(t)?t.replace(rn,"\\$&"):t}function le(){var t=arguments,e=re(t[0]);return t.length<3?e:e.replace(t[1],t[2])}function he(t){return t=re(t),t&&Je.test(t)?t.replace(Qe,p):t}function fe(t){return function(){return t}}function de(t){return t}function pe(t){return Z("function"==typeof t?t:Y(t,!0))}function me(t){return kt(t)?nt(t):rt(t)}var ve,ge="4.6.1",xe=200,ye="__lodash_hash_undefined__",be=1,we=2,Ee=1/0,Se=9007199254740991,Ae=NaN,Ce="[object Arguments]",_e="[object Array]",Me="[object Boolean]",Oe="[object Date]",Le="[object Error]",$e="[object Function]",Ne="[object GeneratorFunction]",je="[object Map]",ke="[object Number]",Te="[object Object]",Ie="[object RegExp]",Pe="[object Set]",ze="[object String]",Be="[object Symbol]",Re="[object WeakMap]",Ue="[object ArrayBuffer]",Xe="[object Float32Array]",Ye="[object Float64Array]",qe="[object Int8Array]",De="[object Int16Array]",Fe="[object Int32Array]",He="[object Uint8Array]",Ve="[object Uint8ClampedArray]",Ge="[object Uint16Array]",We="[object Uint32Array]",Qe=/&(?:amp|lt|gt|quot|#39|#96);/g,Ze=/[&<>"'`]/g,Je=RegExp(Qe.source),Ke=RegExp(Ze.source),tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,en=/^\w*$/,nn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g,rn=/[\\^$.*+?()[\]{}|]/g,an=RegExp(rn.source),on=/^\s+|\s+$/g,sn=/\\(\\)?/g,un=/\w*$/,cn=/^[-+]0x[0-9a-f]+$/i,ln=/^0b[01]+$/i,hn=/^\[object .+?Constructor\]$/,fn=/^0o[0-7]+$/i,dn=/^(?:0|[1-9]\d*)$/,pn={};pn[Xe]=pn[Ye]=pn[qe]=pn[De]=pn[Fe]=pn[He]=pn[Ve]=pn[Ge]=pn[We]=!0,pn[Ce]=pn[_e]=pn[Ue]=pn[Me]=pn[Oe]=pn[Le]=pn[$e]=pn[je]=pn[ke]=pn[Te]=pn[Ie]=pn[Pe]=pn[ze]=pn[Re]=!1;var mn={};mn[Ce]=mn[_e]=mn[Ue]=mn[Me]=mn[Oe]=mn[Xe]=mn[Ye]=mn[qe]=mn[De]=mn[Fe]=mn[je]=mn[ke]=mn[Te]=mn[Ie]=mn[Pe]=mn[ze]=mn[Be]=mn[He]=mn[Ve]=mn[Ge]=mn[We]=!0,mn[Le]=mn[$e]=mn[Re]=!1;var vn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},gn={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},xn={"function":!0,object:!0},yn=parseInt,bn=xn[typeof exports]&&exports&&!exports.nodeType?exports:ve,wn=xn[typeof module]&&module&&!module.nodeType?module:ve,En=wn&&wn.exports===bn?bn:ve,Sn=u(bn&&wn&&"object"==typeof global&&global),An=u(xn[typeof self]&&self),Cn=u(xn[typeof window]&&window),_n=u(xn[typeof this]&&this),Mn=Sn||Cn!==(_n&&_n.window)&&Cn||An||_n||Function("return this")(),On=Array.prototype,Ln=Object.prototype,$n=Function.prototype.toString,Nn=Ln.hasOwnProperty,jn=Ln.toString,kn=RegExp("^"+$n.call(Nn).replace(rn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Tn=En?Mn.Buffer:ve,In=Mn.Symbol,Pn=Mn.Uint8Array,zn=Object.getPrototypeOf,Bn=Object.getOwnPropertySymbols,Rn=Object.create,Un=Ln.propertyIsEnumerable,Xn=On.splice,Yn=Math.ceil,qn=Object.keys,Dn=Math.max,Fn=Ct(Mn,"Map"),Hn=Ct(Mn,"Set"),Vn=Ct(Mn,"WeakMap"),Gn=Ct(Object,"create"),Wn=Fn?$n.call(Fn):"",Qn=Hn?$n.call(Hn):"",Zn=Vn?$n.call(Vn):"",Jn=In?In.prototype:ve,Kn=Jn?Jn.valueOf:ve,tr=Jn?Jn.toString:ve,er=gt(D),nr=xt(),rr=nt("length"),ir=Bn||function(){return[]};(Fn&&_t(new Fn)!=je||Hn&&_t(new Hn)!=Pe||Vn&&_t(new Vn)!=Re)&&(_t=function(t){var e=jn.call(t),n=e==Te?t.constructor:null,r="function"==typeof n?$n.call(n):"";if(r)switch(r){case Wn:return je;case Qn:return Pe;case Zn:return Re}return e});var ar=Array.isArray,or=Tn?function(t){return t instanceof Tn}:fe(!1),sr=yt();v.prototype=Gn?Gn(null):Ln,w.prototype.clear=E,w.prototype["delete"]=S,w.prototype.get=A,w.prototype.has=C,w.prototype.set=_,M.prototype.clear=O,M.prototype["delete"]=L,M.prototype.get=$,M.prototype.has=N,M.prototype.set=j,m.constant=fe,m.iteratee=pe,m.keys=oe,m.map=Xt,m.property=me,m.range=sr,m.toPairs=se,m.eq=Yt,m.escape=ue,m.escapeRegExp=ce,m.forEach=Ut,m.get=ie,m.hasIn=ae,m.identity=de,m.isArguments=qt,m.isArray=ar,m.isArrayLike=Dt,m.isArrayLikeObject=Ft,m.isBuffer=or,m.isFunction=Ht,m.isLength=Vt,m.isNative=Qt,m.isNumber=Zt,m.isObject=Gt,m.isObjectLike=Wt,m.isString=Jt,m.isSymbol=Kt,m.isTypedArray=te,m.isUndefined=ee,m.last=Rt,m.replace=le,m.toNumber=ne,m.toString=re,m.unescape=he,m.each=Ut,m.VERSION=ge,(Cn||An||{})._=m,Mn._=m}.call(this),Math.log10=Math.log10||function(t){return Math.log(t)/Math.LN10},String.prototype.format=function(){var t=this,e=arguments;1==arguments.length&&(_.isArray(arguments[0])||_.isObject(arguments[0]))&&(e=arguments[0]);for(var n in e)if(e.hasOwnProperty(n)){var r=n;n.match(/^\{.*\}$/)||(n="{"+n+"}");var i=new RegExp(_.escapeRegExp(n),"g");t=t.replace(i,e[r])}return t};var modal=function(){var t={};return t.show=function(t){var e=$(t);e.removeClass("hidden visible"),setTimeout(function(){e.addClass("visible")},1)},t.hide=function(t){var e=$(t);e.removeClass("visible"),setTimeout(function(){e.addClass("hidden")},500)},t.init=function(){$(".Modal").on("click",function(){$(this).hasClass("no-close")||t.hide(this)}),$(".Dialog").on("click",function(t){t.stopImmediatePropagation()}),$(window).on("keydown",function(e){27==e.which&&t.hide(".Modal")})},t}(),notify=function(){var t,e,n={},r="#notif";return n.show=function(i,a){$(r).html(i),modal.show(r),clearTimeout(t),clearTimeout(e),_.isUndefined(a)||(t=setTimeout(n.hide,a))},n.hide=function(){var t=$(r);t.removeClass("visible"),e=setTimeout(function(){t.addClass("hidden")},250)},n.init=function(){$(r).on("click",function(){n.hide(this)})},n}();$().ready(function(){setInterval(function(){$(".anim-dots").each(function(t){var e=$(t),n=e.html()+".";5==n.length&&(n="."),e.html(n)})},1e3),$("input[type=number]").on("mousewheel",function(t){var e=+$(this).val(),n=+($(this).attr("step")||1),r=$(this).attr("min"),i=$(this).attr("max");if(t.wheelDelta>0?e+=n:e-=n,_.isUndefined(r)||(e=Math.max(e,r)),_.isUndefined(i)||(e=Math.min(e,i)),$(this).val(e),"createEvent"in document){var a=document.createEvent("HTMLEvents");a.initEvent("change",!1,!0),$(this)[0].dispatchEvent(a)}else $(this)[0].fireEvent("onchange");t.preventDefault()}),modal.init(),notify.init()});var page_wifi=function(){function t(t,e){if(200!=e)return void n(5e3);t=JSON.parse(t);var a=!bool(t.result.inProgress)&&t.result.APs.length>0;if(n(a?15e3:1e3),a){var o=$("#ap-list");$(".AP").remove(),o.toggle(a),$("#ap-loader").toggle(!a),t.result.APs.sort(function(t,e){return e.rssi-t.rssi}).forEach(function(t){if(t.enc=parseInt(t.enc),!(t.enc>4)){var e=document.createElement("div"),n=$(e).data("ssid",t.essid).data("pwd",0!=t.enc).addClass("AP");t.essid==r.current&&n.addClass("selected");var a=document.createElement("div");$(a).addClass("inner").htmlAppend('
{0}
'.format(t.rssi_perc)).htmlAppend('
{0}
'.format(_.escape(t.essid))).htmlAppend('
{0}
'.format(i[t.enc]));n.on("click",function(){var t=$(this);$("#conn-essid").val(t.data("ssid")),$("#conn-passwd").val(""),t.data("pwd")?modal.show("#psk-modal"):$("#conn-form").submit()}),e.appendChild(a), -o[0].appendChild(e)}})}}function e(){$().get(_root+"/wifi/scan",t)}function n(t){setTimeout(e,t)}var r={},i=["Open","WEP","WPA","WPA2","WPA/WPA2"];return r.init=function(){e()},r}(),page_waveform=function(){function t(t){var e,n,r=window.matchMedia("screen and (min-width: 544px)"),i=!r.matches,o="FFT"==t.stats.format;o?(e="Frequency - [ Hz ]",n="Magnitude - [ mA ]"):(e="Sample time - [ ms ]",n="Current - [ mA ]");var s=Math.max(-t.stats.min,t.stats.max),l=Math.max(s,10);$("#stat-count").html(t.stats.count),$("#stat-f-s").html(numfmt(t.stats.freq,2)),$("#stat-i-peak").html(numfmt(s,2)),$("#stat-i-rms").html(numfmt(t.stats.rms,2)),$(".stats").removeClass("invis");var h=o?t.stats.freq/t.stats.count:1e3/t.stats.freq,f=_.map(t.samples,function(t,e){return{x:e*h,y:t}}),d=[Chartist.plugins.zoom({resetOnRightMouseBtn:!0,onZoom:function(t,e){a=e,u=t.options.axisX.highLow,c=t.options.axisY.highLow}})];i||d.push(Chartist.plugins.ctAxisTitle({axisX:{axisTitle:e,offset:{x:0,y:55}},axisY:{axisTitle:n,flipText:!0,offset:{x:0,y:15}}}));var p,m,v,g;u?(p=u.high,m=u.low,v=c.high,g=c.low):(v=o?void 0:l,g=o?0:-l),new Chartist.Line("#chart",{series:[{name:"a",data:f}]},{showPoint:!1,showArea:o,fullWidth:!0,chartPadding:i?{right:20,bottom:5,left:0}:{right:25,bottom:30,left:25},series:{a:{lineSmooth:Chartist.Interpolation.monotoneCubic()}},axisX:{type:Chartist.AutoScaleAxis,high:p,low:m},axisY:{type:Chartist.AutoScaleAxis,high:v,low:g},explicitBounds:{xLow:0,yLow:o?0:void 0,xHigh:f[f.length-1].x},plugins:d})}function e(e,n){if(f=!1,200!=n)errorMsg("Request failed.",1e3);else{var i=JSON.parse(e);i.success?($(".chartexport").removeClass("hidden"),v=i,t(i)):errorMsg("Sampling failed.",1e3)}d&&(m=setTimeout(r,Math.max(0,p-msElapsed(s))))}function n(){g.count=$("#count").val(),g.freq=$("#freq").val()*("fft"==o?2:1)}function r(){f&&(errorMsg("Request already pending - aborting."),l.abort()),f=!0,s=msNow();var t=g.count,n=g.freq,r=_root+"/measure/"+o+"?n="+t+"&fs="+n;return l=$().get(r,e,estimateLoadTime(n,t)),!0}function i(){p=+$("#ar-time").val(),n(),d=!d,d?r():clearTimeout(m),$("#ar-btn").toggleClass("btn-blue").toggleClass("btn-red").val(d?"Stop":"Auto")}var a,o,s,u,c,l,h={},f=!1,d=!1,p=1,m=-1,v=null,g={count:0,freq:0};return h.init=function(t){function e(){n(),r()}o=t,$("#load").on("click",e),$(".chartexport a").on("click",function(){var t=$(this).data("sep"),e="",n="fft"==o,r=n?v.stats.freq/v.stats.count:1e3/v.stats.freq,i=n?3:2;switch(t){case"space":e=v.samples.join(" ");break;case"comma":e=v.samples.join(",");break;case"newline":e=v.samples.join("\n");break;case"csv":e=_.map(v.samples,function(t,e){return numfmt(e*r,i)+","+t}).join("\n")}if(copyToClipboard(e))infoMsg("Copy success!");else{var a=$("#copybox");a.removeClass("hidden"),a.val(e)}}),$("#count,#freq").on("keyup",function(t){13==t.which&&e()}),$("#chart").on("contextmenu",function(t){return a&&a(),a=null,u=null,c=null,t.preventDefault(),!1}),$("#ar-btn").on("click",i)},h}(),page_spectrogram=function(){function t(t){var e,n,r,i;t=Math.log10(1+t),t>2&&(t=2),0>t&&(t=0);for(var a=0;a=s&&(e=s,r=o),s>=t){n=s,i=o;break}}var u=(t-e)/(n-e);e==n&&(u=0);var c=Math.round(r[1]+(i[1]-r[1])*u),l=Math.round(r[2]+(i[2]-r[2])*u),h=Math.round(r[3]+(i[3]-r[3])*u);return"rgb("+c+","+l+","+h+")"}function e(){var t=c.getImageData(g.x+g.dx,g.y,g.w-g.dx,g.h+10);c.fillStyle="black",c.fillRect(g.x,g.y,g.w,g.h),c.clearRect(g.x,g.y+g.h+1,g.w,10),c.putImageData(t,g.x,g.y)}function n(n){e();for(var r=x.sampCount/2,i=0;r>i;i++){var a;if(i*g.dy>g.h)break;a=i>n.length?"#000":t(n[i]),c.fillStyle=a;var o=g.x+g.w-g.dx,s=g.y+g.h-(i+1)*g.dy,u=g.dx,l=g.dy;s=950){p=msNow();var h=!1;msElapsed(m)>9500&&(h=!0,m=msNow()),c.strokeStyle="white",c.beginPath(),c.moveTo(g.x+g.w-.5,g.y+g.h+1),c.lineTo(g.x+g.w-.5,g.y+g.h+1+(h?6:2)),c.stroke()}}function r(t,e){if(h=!1,200==e)try{var r=JSON.parse(t);r.success?n(r.samples):errorMsg("Sampling failed.",1e3)}catch(a){errorMsg(a)}else errorMsg("Request failed.",1e3);y&&(l=setTimeout(i,Math.max(0,x.interval-msElapsed(d))))}function i(){h&&(errorMsg("Request already pending - aborting."),f.abort()),h=!0,d=msNow();var t=x.freq,e=x.sampCount,n=_root+"/measure/fft?n="+e+"&fs="+t;return f=$().get(n,r,estimateLoadTime(t,e)),!0}function a(){for(var e=8,n=10,r=g.h-12,i=g.y+6,a=g.x-e-n,o=100/r,s=0;r>s;s++){var u=t(s*o),l=t((s+1)*o),h=Math.floor(i+r-(s+1)),f=c.createLinearGradient(0,h+1,0,h);f.addColorStop(0,u),f.addColorStop(1,l),c.fillStyle=f,c.fillRect(a,h,n,1)}c.strokeStyle="#000",c.strokeRect(a-.5,i-.5,n+1,r+1),o=100/r,c.font="12px sans-serif",c.fillStyle="white",c.textAlign="right";for(var s=0;s<=g.h;s+=r/10)c.fillText(Math.round(s*o)+"",g.x-e-n-e,i+r-s+3)}function o(){var t=8,e=g.x+g.w,n=e+t,r=g.y,i=g.h,a=70;c.clearRect(e+.5,r-10,a,i+20);for(var o,s=x.freq/2/(x.sampCount/2),u=g.h/g.dy,l=u*s,h=[10,25,50],f=1,d=!1;;){for(var p=0;p=p;p+=o){if(p>=u){var m=p-u;if(m>o/2)break;p=u}var v=p*(l/u);v=v>=1e6?numfmt(v/1e6,2)+"M":v>=1e3?numfmt(v/1e3,2)+"k":numfmt(v,1);var y=Math.round(r+i-g.dy*p);if(c.fillText(v,n,y+4),c.beginPath(),c.moveTo(e,y+.5),c.lineTo(e+t/2,y+.5),c.stroke(),p>=u)break}c.font="16px sans-serif",c.save(),c.translate(e+50,g.y+g.h/2),c.rotate(Math.PI/2),c.textAlign="center",c.fillText("Frequency - [Hz]",0,0),c.restore()}function s(){x.interval=+$("#interval").val(),x.freq=2*+$("#freq").val(),x.sampCount=+$("#count").val(),g.dx=+$("#tile-x").val(),g.dy=+$("#tile-y").val()}function u(){c.fillStyle="#000",c.fillRect(g.x,g.y,g.w,g.h),c.strokeStyle="white",c.strokeRect(g.x-.5,g.y-.5,g.w+1,g.h+1)}var c,l,h,f,d,p,m,v={},g={x:50,y:10,w:740,h:512,dx:1,dy:1},x={interval:0,sampCount:0,freq:0},y=!1,b=[[0,0,0,0],[.1,41,17,41],[.25,34,17,78],[.6,17,30,105],[1,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.9,223,217,86],[1.97,248,222,176],[1.99,255,237,222],[2,255,255,255]];return v.init=function(){var t=$("#sg")[0];c=t.getContext("2d"),u(),s(),a(),o(),p=msNow()-1e4,m=msNow()-1e4,$("#count").on("change",function(){var t=+$("#count").val(),e=Math.max(1,g.h/(t/2));$("#tile-x").val(Math.max(4,e)),$("#tile-y").val(e)}),$("#tile-y").on("change",function(){$("#tile-x").val(Math.max(4,$(this).val()))}),$("#go-btn").on("click",function(){y=!y,y?(s(),o(),i()):clearTimeout(l),$("#go-btn").toggleClass("btn-green").toggleClass("btn-red").html(y?"Stop":"Start")})},v}(),page_status=function(){function t(t,a){if(200!=a)errorMsg("Update failed.");else try{var o=JSON.parse(t);n.j=o,$(".sta-only").toggle(o.sta),$(".ap-only").toggle(o.ap),$("#uptime").html(o.uptime),$("#heap").html(o.heap+" bytes"),$("#wmode").html(o.wifiMode),o.sta&&($("#staSSID").html(o.sta.SSID),$("#staRSSIperc").html(o.sta.RSSIperc),$("#staRSSI").html(o.sta.RSSI),$("#staMAC").html(o.sta.MAC)),o.ap&&($("#apSSID").html(o.ap.SSID),$("#apHidden").html(o.ap.hidden?"Yes":"No"),$("#apAuth").html(o.ap.auth),$(".ap-auth-only").toggle("Open"!=o.ap.auth),$("#apPwd").html(o.ap.pwd),$("#apChan").html(o.ap.chan),$("#apMAC").html(o.ap.MAC))}catch(s){errorMsg(s)}i||setTimeout(e,r)}function e(){$().get(_root+"/system/status",t)}var n={};n.j={};var r=1e4,i=!1;return n.trigReset=function(){var t="#reset-modal";$().get(_root+"/system/reset",function(n,r){if(200==r){modal.show(t),i=!0;var a=setInterval(function(){$().get(_root+"/system/ping",function(n,r){200==r&&(modal.hide(t),e(),clearInterval(a),i=!1)},{timeout:500})},1e3)}})},n.init=function(){e()},n}(),page_mon=function(){function t(t){$("#hasref").html(t?"OK":"Not set!")}function e(){var t=$("#rep-svc-xv")[0].checked;t?$(".xv-only").removeClass("hidden"):$(".xv-only").addClass("hidden")}var n={};return n.captureRef=function(){$().get(_root+"/mon/setref",function(e,n){if(200!=n)errorMsg("Operation failed.");else try{var r=JSON.parse(e);t(r.success)}catch(i){errorMsg(i),t(!1)}})},n.compareNow=function(){$().get(_root+"/mon/compare",function(t,e){if(200!=e)errorMsg("Operation failed.");else try{var n=JSON.parse(t);if(!n.success)throw"Capture failed.";$("#actual-dev").html(numfmt(n.deviation,2)),$("#actual-rms").html(numfmt(n.rms,2))}catch(r){errorMsg(r),$("#actual-dev").html("--"),$("#actual-rms").html("--")}})},n.init=function(){e(),$("#rep-svc-xv,#rep-svc-ts").on("change",e),setInterval(function(){$().get(_root+"/mon/status",function(t,e){if(200==e)try{var n=JSON.parse(t);n.success&&($("#actual-dev").html(numfmt(n.deviation,2)),$("#actual-rms").html(numfmt(n.rms,2)))}catch(r){errorMsg(r),$("#actual-dev").html("--"),$("#actual-rms").html("--")}})},1e4)},n}(); \ No newline at end of file +function bool(t){return 1===t||"1"===t||t===!0||"true"===t}function numfmt(t,e){var n=Math.pow(10,e);return Math.round(t*n)/n}function estimateLoadTime(t,e){return 1e3/t*e+1500}function msNow(){return+new Date}function msElapsed(t){return msNow()-t}function copyToClipboard(t){if(!document.execCommand)return!1;var e="_hiddenCopyText_";if(n=document.getElementById(e),!n){var n=document.createElement("textarea");n.style.position="absolute",n.style.left="-9999px",n.style.top="0",n.id=e,document.body.appendChild(n)}n.textContent=t;var r=document.activeElement;n.focus(),n.setSelectionRange(0,n.value.length);var o;try{o=document.execCommand("copy")}catch(u){o=!1}return r&&"function"==typeof r.focus&&r.focus(),n.textContent="",o}function errorMsg(t,e){$("#notif").addClass("error"),notify.show(t,e||3e3)}function infoMsg(t,e){$("#notif").removeClass("error"),notify.show(t,e||3e3)}!function(){"use strict";function t(){var t;for(h=!0,t=0;t=0;n-=1)t(e[n])}function r(t){return t.replace(/-\w/g,function(t){return t.charAt(1).toUpperCase()})}function o(t,e){return t.currentStyle?t.currentStyle[r(e)]:m.getComputedStyle?m.getComputedStyle(t,null).getPropertyValue(e):null}function u(t,e){return encodeURIComponent(t).replace(/%20/g,"+")+"="+encodeURIComponent(e).replace(/%20/g,"+")}function a(t,e,n){try{t.style[r(e)]=n}catch(o){}}function i(t){t.style.display="","none"===o(t,"display")&&(t.style.display="block")}function c(t){var e,r,o,a="";if(t.constructor===Object){for(e in t)if(t.hasOwnProperty(e))if(t[e].constructor===Array)for(r=0;r0&&(a+="&"+u(e.name,e.value));break;case"select-multiple":for(o=0;o0?a.substring(1):""}function f(t,e,r){var o,u,a,i=!1;return t&&(o=t.split(/\s+/),n(function(t){for(a=0;a0?b[0].className.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"").replace(/\s+/," "):void 0},e.setClass=function(t){return(t||""===t)&&n(function(e){e.className=t},b),e},e.addClass=function(t){return t&&n(function(e){e.className+=" "+t},b),e},e.removeClass=function(t){return f(t,"remove",b),e},e.toggleClass=function(t){return f(t,"toggle",b),e},e.hasClass=function(t){return f(t,"has",b)},e.html=function(t){return t||""===t?(n(function(e){e.innerHTML=t},b),e):b[0]?b[0].innerHTML:void 0},e.htmlBefore=function(t){return s(t,"before",b),e},e.htmlAfter=function(t){return s(t,"after",b),e},e.htmlAppend=function(t){return s(t,"append",b),e},e.htmlPrepend=function(t){return s(t,"prepend",b),e},e.attr=function(t,r){if(t){if(t=t.toLowerCase(),"undefined"!=typeof r)return n(function(e){"style"===t?e.style.cssText=r:"class"===t?e.className=r:e.setAttribute(t,r)},b),e;if(b[0])if("style"===t){if(b[0].style.cssText)return b[0].style.cssText}else if("class"===t){if(b[0].className)return b[0].className}else if(b[0].getAttribute(t))return b[0].getAttribute(t)}},e.data=function(t,n){return t?e.attr("data-"+t,n):void 0},e.val=function(t){var r,o,u;if(!_.isUndefined(t))return n(function(e){switch(e.nodeName){case"SELECT":for(("string"==typeof t||"number"==typeof t)&&(t=[t]),o=0;o1?r:r[0];case"INPUT":case"TEXTAREA":case"BUTTON":return b[0].value}},e.checked=function(t){return"boolean"==typeof t?(n(function(e){"INPUT"!==e.nodeName||"checkbox"!==e.type&&"radio"!==e.type||(e.checked=t)},b),e):!b[0]||"INPUT"!==b[0].nodeName||"checkbox"!==b[0].type&&"radio"!==b[0].type?void 0:!!b[0].checked},e.on=function(r,o){return(t===m||t===g)&&(b=[t]),n(function(t){g.addEventListener?t.addEventListener(r,o,!1):g.attachEvent&&(t[r+o]=function(){return o.apply(t,arguments)},t.attachEvent("on"+r,t[r+o]))},b),e},e.off=function(r,o){return(t===m||t===g)&&(b=[t]),n(function(t){g.addEventListener?t.removeEventListener(r,o,!1):g.attachEvent&&(t.detachEvent("on"+r,t[r+o]),t[r+o]=null)},b),e},e.ajax=function(t,e,n,r){var o,u,a=c(b),i=e?e.toUpperCase():"GET";_.isNumber(r)&&(r={timeout:r});var f=_.extend({},{nocache:!0,timeout:5e3,loader:!0},r);if(a&&"GET"===i&&(t+=-1===t.indexOf("?")?"?"+a:"&"+a,a=null),o=new XMLHttpRequest){if(f.nocache){var s=(+new Date).toString(36);t+=(-1===t.indexOf("?")?"?":"&")+"_="+s}f.loader&&$("#loader").addClass("show"),o.open(i,t,!0),o.timeout=f.timeout,u=setTimeout(function(){errorMsg("XHR timed out."),o.abort(),f.loader&&$("#loader").removeClass("show")},f.timeout+10),o.onreadystatechange=function(){4===o.readyState&&(f.loader&&$("#loader").removeClass("show"),n&&0!=o.status&&n(o.responseText,o.status),clearTimeout(u))},o.setRequestHeader("X-Requested-With","XMLHttpRequest"),"POST"===i&&o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),o.send(a)}return o},e.get=function(t,n,r){return e.ajax(t,"get",n,r)},e.post=function(t,n,r){return e.ajax(t,"post",n,r)},e}var p=[],d=[],h=!1,v=!1,g=document,m=window;g.addEventListener?(g.addEventListener("DOMContentLoaded",t,!1),m.addEventListener("load",e,!1)):g.attachEvent?(g.attachEvent("onreadystatechange",t),m.attachEvent("onload",e)):m.onload=e,m.$=l}(),function(){function t(t,e){return t.set(e[0],e[1]),t}function e(t,e){return t.add(e),t}function n(t,e,n){var r=n.length;switch(r){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}function r(t,e){for(var n=-1,r=t.length;++n-1&&t%1==0&&e>t}function d(t){for(var e,n=[];!(e=t.next()).done;)n.push(e.value);return n}function h(t){var e=-1,n=Array(t.size);return t.forEach(function(t,r){n[++e]=[r,t]}),n}function v(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[++e]=t}),n}function g(t){return $n[t]}function m(){}function y(){}function b(t,e){return _(t,e)&&delete t[e]}function w(t,e){if(ur){var n=t[e];return n===Ce?je:n}return Bn.call(t,e)?t[e]:je}function _(t,e){return ur?t[e]!==je:Bn.call(t,e)}function E(t,e,n){t[e]=ur&&n===je?Ce:n}function j(t){var e=-1,n=t?t.length:0;for(this.clear();++en)return!1;var r=t.length-1;return n==r?t.pop():Qn.call(t,n,1),!0}function R(t,e){var n=U(t,e);return 0>n?je:t[n][1]}function I(t,e){return U(t,e)>-1}function U(t,e){for(var n=t.length;n--;)if(Gt(t[n][0],e))return n;return-1}function F(t,e,n){var r=U(t,e);0>r?t.push([e,n]):t[r][1]=n}function B(t,e,n){var r=t[e];Bn.call(t,e)&&Gt(r,n)&&(n!==je||e in t)||(t[e]=n)}function q(t,e){return t&&mt(e,pe(e),t)}function H(t){return"function"==typeof t?t:we}function W(t){return mr(t)?t:Ht(t)}function D(t,e,n,o,u,a,i){var c;if(o&&(c=a?o(t,u,a,i):o(t)),c!==je)return c;if(!Zt(t))return t;var f=mr(t);if(f){if(c=St(t),!e)return gt(t,c)}else{var s=Nt(t),p=s==Fe||s==Be;if(yr(t))return ft(t,e);if(s==We||s==Me||p&&!a){if(l(t))return a?t:{};if(c=Lt(p?{}:t),!e)return c=q(c,t),n?bt(t,c):c}else{if(!An[s])return a?t:{};c=Mt(t,s,e)}}i||(i=new T);var d=i.get(t);return d?d:(i.set(t,c),(f?r:z)(t,function(r,u){B(c,u,D(r,e,n,o,u,t,i))}),n&&!f?bt(t,c):c)}function X(t){return Zt(t)?Yn(t):{}}function z(t,e){return t&&hr(t,e,pe)}function G(t,e){e=It(e,t)?[e+""]:W(e);for(var n=0,r=e.length;null!=t&&r>n;)t=t[e[n++]];return n&&n==r?t:je}function V(t,e){return Bn.call(t,e)||"object"==typeof t&&e in t&&null===Vn(t)}function J(t,e){return e in Object(t)}function Y(t,e,n,r,o){return t===e?!0:null==t||null==e||!Zt(t)&&!te(e)?t!==t&&e!==e:K(t,e,Y,n,r,o)}function K(t,e,n,r,o,u){var a=mr(t),i=mr(e),c=Pe,f=Pe;a||(c=Nt(t),c=c==Me?We:c),i||(f=Nt(e),f=f==Me?We:f);var s=c==We&&!l(t),p=f==We&&!l(e),d=c==f;if(d&&!s)return u||(u=new T),a||ue(t)?At(t,e,n,r,o,u):xt(t,e,c,n,r,o,u);if(!(o&Te)){var h=s&&Bn.call(t,"__wrapped__"),v=p&&Bn.call(e,"__wrapped__");if(h||v)return u||(u=new T),n(h?t.value():t,v?e.value():e,r,o,u)}return d?(u||(u=new T),$t(t,e,n,r,o,u)):!1}function Q(t,e,n,r){var o=n.length,u=o,a=!r;if(null==t)return!u;for(t=Object(t);o--;){var i=n[o];if(a&&i[2]?i[1]!==t[i[0]]:!(i[0]in t))return!1}for(;++oe&&(e=-e>o?0:o+e),n=n>o?o:n,0>n&&(n+=o),o=e>n?0:n-e>>>0,e>>>=0;for(var u=Array(o);++r1?n[o-1]:je,a=o>2?n[2]:je;for(u="function"==typeof u?(o--,u):je,a&&Rt(n[0],n[1],a)&&(u=3>o?je:u,o=1),e=Object(e);++re?1:-1:ce(r)||0,it(e,n,r,t)}}function At(t,e,n,r,o,u){var i=-1,c=o&Te,f=o&Oe,s=t.length,l=e.length;if(s!=l&&!(c&&l>s))return!1;var p=u.get(t);if(p)return p==e;var d=!0;for(u.set(t,e);++i-1&&t%1==0&&ke>=t}function Zt(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function te(t){return!!t&&"object"==typeof t}function ee(t){return null==t?!1:Kt(t)?Hn.test(Fn.call(t)):te(t)&&(l(t)?Hn:wn).test(t)}function ne(t){return"number"==typeof t||te(t)&&qn.call(t)==He}function re(t){return"string"==typeof t||!mr(t)&&te(t)&&qn.call(t)==ze}function oe(t){return"symbol"==typeof t||te(t)&&qn.call(t)==Ge}function ue(t){return te(t)&&Qt(t.length)&&!!jn[qn.call(t)]}function ae(t){return t===je}function ie(t){if(!t)return 0===t?t:0;if(t=ce(t),t===Ne||t===-Ne){var e=0>t?-1:1;return e*Se}var n=t%1;return t===t?n?t-n:t:0}function ce(t){if(Zt(t)){var e=Kt(t.valueOf)?t.valueOf():t;t=Zt(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(vn,"");var n=bn.test(t);return n||_n.test(t)?On(t.slice(2),n?2:8):yn.test(t)?Le:+t}function fe(t){if("string"==typeof t)return t;if(null==t)return"";if(oe(t))return pr?pr.call(t):"";var e=t+"";return"0"==e&&1/t==-Ne?"-0":e}function se(t,e,n){var r=null==t?je:G(t,e);return r===je?n:r}function le(t,e){return kt(t,e,J)}function pe(t){var e=Ft(t);if(!e&&!Jt(t))return tt(t);var n=Pt(t),r=!!n,o=n||[],u=o.length;for(var a in t)!V(t,a)||r&&("length"==a||p(a,u))||e&&"constructor"==a||o.push(a);return o}function de(t){for(var e=-1,n=Ft(t),r=et(t),o=r.length,u=Pt(t),a=!!u,i=u||[],c=i.length;++e"'`]/g,cn=RegExp(un.source),fn=RegExp(an.source),sn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ln=/^\w*$/,pn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g,dn=/[\\^$.*+?()[\]{}|]/g,hn=RegExp(dn.source),vn=/^\s+|\s+$/g,gn=/\\(\\)?/g,mn=/\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,bn=/^0b[01]+$/i,wn=/^\[object .+?Constructor\]$/,_n=/^0o[0-7]+$/i,En=/^(?:0|[1-9]\d*)$/,jn={};jn[Ye]=jn[Ke]=jn[Qe]=jn[Ze]=jn[tn]=jn[en]=jn[nn]=jn[rn]=jn[on]=!0,jn[Me]=jn[Pe]=jn[Je]=jn[Re]=jn[Ie]=jn[Ue]=jn[Fe]=jn[qe]=jn[He]=jn[We]=jn[De]=jn[Xe]=jn[ze]=jn[Ve]=!1;var An={};An[Me]=An[Pe]=An[Je]=An[Re]=An[Ie]=An[Ye]=An[Ke]=An[Qe]=An[Ze]=An[tn]=An[qe]=An[He]=An[We]=An[De]=An[Xe]=An[ze]=An[Ge]=An[en]=An[nn]=An[rn]=An[on]=!0,An[Ue]=An[Fe]=An[Ve]=!1;var xn={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},$n={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Cn={"function":!0,object:!0},On=parseInt,Tn=Cn[typeof exports]&&exports&&!exports.nodeType?exports:je,Nn=Cn[typeof module]&&module&&!module.nodeType?module:je,kn=Nn&&Nn.exports===Tn?Tn:je,Sn=f(Tn&&Nn&&"object"==typeof global&&global),Ln=f(Cn[typeof self]&&self),Mn=f(Cn[typeof window]&&window),Pn=f(Cn[typeof this]&&this),Rn=Sn||Mn!==(Pn&&Pn.window)&&Mn||Ln||Pn||Function("return this")(),In=Array.prototype,Un=Object.prototype,Fn=Function.prototype.toString,Bn=Un.hasOwnProperty,qn=Un.toString,Hn=RegExp("^"+Fn.call(Bn).replace(dn,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Wn=kn?Rn.Buffer:je,Dn=Rn.Reflect,Xn=Rn.Symbol,zn=Rn.Uint8Array,Gn=Dn?Dn.enumerate:je,Vn=Object.getPrototypeOf,Jn=Object.getOwnPropertySymbols,Yn=Object.create,Kn=Un.propertyIsEnumerable,Qn=In.splice,Zn=Math.ceil,tr=Object.keys,er=Math.max,nr=Tt(Rn,"Map"),rr=Tt(Rn,"Set"),or=Tt(Rn,"WeakMap"),ur=Tt(Object,"create"),ar=!Kn.call({valueOf:1},"valueOf"),ir=nr?Fn.call(nr):"",cr=rr?Fn.call(rr):"",fr=or?Fn.call(or):"",sr=Xn?Xn.prototype:je,lr=sr?sr.valueOf:je,pr=sr?sr.toString:je,dr=_t(z),hr=Et();Gn&&!Kn.call({valueOf:1},"valueOf")&&(et=function(t){return d(Gn(t))});var vr=ut("length"),gr=Jn||function(){return[]};(nr&&Nt(new nr)!=qe||rr&&Nt(new rr)!=Xe||or&&Nt(new or)!=Ve)&&(Nt=function(t){var e=qn.call(t),n=e==We?t.constructor:null,r="function"==typeof n?Fn.call(n):"";if(r)switch(r){case ir:return qe;case cr:return Xe;case fr:return Ve}return e});var mr=Array.isArray,yr=Wn?function(t){return t instanceof Wn}:be(!1),br=wt(function(t,e){if(ar||Ft(e)||Jt(e))return void mt(e,de(e),t);for(var n in e)B(t,n,e[n])}),wr=jt();y.prototype=ur?ur(null):Un,j.prototype.clear=A,j.prototype["delete"]=x,j.prototype.get=$,j.prototype.has=C,j.prototype.set=O,T.prototype.clear=N,T.prototype["delete"]=k,T.prototype.get=S,T.prototype.has=L,T.prototype.set=M,m.assignIn=br,m.constant=be,m.iteratee=_e,m.keys=pe,m.keysIn=de,m.map=Xt,m.property=Ee,m.range=wr,m.rest=zt,m.toPairs=he,m.extend=br,m.eq=Gt,m.escape=ve,m.escapeRegExp=ge,m.forEach=Dt,m.get=se,m.hasIn=le,m.identity=we,m.isArguments=Vt,m.isArray=mr,m.isArrayLike=Jt,m.isArrayLikeObject=Yt,m.isBuffer=yr,m.isFunction=Kt,m.isLength=Qt,m.isNative=ee,m.isNumber=ne,m.isObject=Zt,m.isObjectLike=te,m.isString=re,m.isSymbol=oe,m.isTypedArray=ue,m.isUndefined=ae,m.last=Wt,m.replace=me,m.toInteger=ie,m.toNumber=ce,m.toString=fe,m.unescape=ye,m.each=Dt,m.VERSION=Ae,(Mn||Ln||{})._=m,Rn._=m}.call(this),Math.log10=Math.log10||function(t){return Math.log(t)/Math.LN10},String.prototype.format=function(){var t=this,e=arguments;1==arguments.length&&(_.isArray(arguments[0])||_.isObject(arguments[0]))&&(e=arguments[0]);for(var n in e)if(e.hasOwnProperty(n)){var r=n;n.match(/^\{.*\}$/)||(n="{"+n+"}");var o=new RegExp(_.escapeRegExp(n),"g");t=t.replace(o,e[r])}return t};var modal=function(){var t={};return t.show=function(t){var e=$(t);e.removeClass("hidden visible"),setTimeout(function(){e.addClass("visible")},1)},t.hide=function(t){var e=$(t);e.removeClass("visible"),setTimeout(function(){e.addClass("hidden")},500)},t.init=function(){$(".Modal").on("click",function(){$(this).hasClass("no-close")||t.hide(this)}),$(".Dialog").on("click",function(t){t.stopImmediatePropagation()}),$(window).on("keydown",function(e){27==e.which&&t.hide(".Modal")})},t}(),notify=function(){var t,e,n={},r="#notif";return n.show=function(o,u){$(r).html(o),modal.show(r),clearTimeout(t),clearTimeout(e),_.isUndefined(u)||(t=setTimeout(n.hide,u))},n.hide=function(){var t=$(r);t.removeClass("visible"),e=setTimeout(function(){t.addClass("hidden")},250)},n.init=function(){$(r).on("click",function(){n.hide(this)})},n}();$().ready(function(){setInterval(function(){$(".anim-dots").each(function(t){var e=$(t),n=e.html()+".";5==n.length&&(n="."),e.html(n)})},1e3),$("input[type=number]").on("mousewheel",function(t){var e=+$(this).val(),n=+($(this).attr("step")||1),r=$(this).attr("min"),o=$(this).attr("max");if(t.wheelDelta>0?e+=n:e-=n,_.isUndefined(r)||(e=Math.max(e,r)),_.isUndefined(o)||(e=Math.min(e,o)),$(this).val(e),"createEvent"in document){var u=document.createEvent("HTMLEvents");u.initEvent("change",!1,!0),$(this)[0].dispatchEvent(u)}else $(this)[0].fireEvent("onchange");t.preventDefault()}),modal.init(),notify.init()});var page_wifi=function(){function t(t,e){if(200!=e)return void n(5e3);t=JSON.parse(t);var u=!bool(t.result.inProgress)&&t.result.APs.length>0;if(n(u?15e3:1e3),u){var a=$("#ap-list");$(".AP").remove(),a.toggle(u),$("#ap-loader").toggle(!u),t.result.APs.sort(function(t,e){return e.rssi-t.rssi}).forEach(function(t){if(t.enc=parseInt(t.enc),!(t.enc>4)){var e=document.createElement("div"),n=$(e).data("ssid",t.essid).data("pwd",0!=t.enc).addClass("AP");t.essid==r.current&&n.addClass("selected");var u=document.createElement("div");$(u).addClass("inner").htmlAppend('
{0}
'.format(t.rssi_perc)).htmlAppend('
{0}
'.format(_.escape(t.essid))).htmlAppend('
{0}
'.format(o[t.enc]));n.on("click",function(){var t=$(this);$("#conn-essid").val(t.data("ssid")),$("#conn-passwd").val(""),t.data("pwd")?modal.show("#psk-modal"):$("#conn-form").submit()}),e.appendChild(u),a[0].appendChild(e)}})}}function e(){$().get(_root+"/wifi/scan",t)}function n(t){setTimeout(e,t)}var r={},o=["Open","WEP","WPA","WPA2","WPA/WPA2"];return r.init=function(){e()},r}(),page_home=function(){var t={};return t.init=function(){},t}(); \ No newline at end of file diff --git a/html_src/node_modules.tar.REMOVED.git-id b/html_src/node_modules.tar.REMOVED.git-id deleted file mode 100644 index 830e9bd..0000000 --- a/html_src/node_modules.tar.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -0648559aed5a9ec1d478b445839bdb807ced7fc5 \ No newline at end of file diff --git a/html_src/page_about.php b/html_src/page_about.php deleted file mode 100644 index ccf6bcd..0000000 --- a/html_src/page_about.php +++ /dev/null @@ -1,48 +0,0 @@ - - -

About

- -
- -

- - - -

© Ondřej Hruška, 2016 <ondra@ondrovo.com>

- -

Katedra měření, FEL ČVUT
Department of Measurement, FEE CTU

-
- -
-

Firmware

- - - - - - - - - - - - - - - - - - - - - - -
Firmwarev%vers_fw%, build %date% at %time%
esp-httpd libv%vers_httpd%
SBMP libv%vers_sbmp%
ESP IoT SDKv%vers_sdk%
STM32 firmwarev%vers_stm%
- -

- The webserver was built using the great esp-httpd - library by Jeroen Domburg. -

-
- - diff --git a/html_src/page_fft.php b/html_src/page_fft.php deleted file mode 100644 index 0b27203..0000000 --- a/html_src/page_fft.php +++ /dev/null @@ -1,73 +0,0 @@ - - -

FFT

- -
-
- - -
-
- - - Hz -
-
- Load -
-
- -
-
-
- - - - - - - - - - - - - - - - - -
Samples
fs
Ipeak
IRMS
-
-  ms - -
-
-
- - - - - - diff --git a/html_src/page_home.php b/html_src/page_home.php new file mode 100644 index 0000000..aa9e734 --- /dev/null +++ b/html_src/page_home.php @@ -0,0 +1,21 @@ + + +

Home

+ +
+

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.

+
+ +
+

Firmware

+

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.

+
+ + + + diff --git a/html_src/page_monitoring.php b/html_src/page_monitoring.php deleted file mode 100644 index b75011d..0000000 --- a/html_src/page_monitoring.php +++ /dev/null @@ -1,73 +0,0 @@ - - -

Monitoring & Reporting

- -
-

Status

- - - - - - - - - -
Reference: - %refStored% - Capture -
Status: - - Δ = %curDeviation%
- IRMS = %curRMS% mA -
- Measure -
-
- -
-

Reporting

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
-   -
-  seconds -
Service: -    -   -
 
-
-
- - - - diff --git a/html_src/page_spectrogram.php b/html_src/page_spectrogram.php deleted file mode 100644 index db5acc4..0000000 --- a/html_src/page_spectrogram.php +++ /dev/null @@ -1,50 +0,0 @@ - - -

Spectrogram

- -
-
- - -
-
- - - × - -
-
- - - Hz -
-
- - - ms -
-
- Start -
-
- -
- -
- - - - diff --git a/html_src/page_status.php b/html_src/page_status.php deleted file mode 100644 index dae7cf1..0000000 --- a/html_src/page_status.php +++ /dev/null @@ -1,99 +0,0 @@ - - -

System Status

- -
-

Runtime

- - - - - - - - - - - - - -
Uptime:%uptime%
Free heap:%heap%
Restart system
-
- -
-

WiFi

- - - - - -
WiFi mode:%wifiMode%
-
- - - - - - - - - - - - diff --git a/html_src/page_waveform.php b/html_src/page_waveform.php deleted file mode 100644 index fc33935..0000000 --- a/html_src/page_waveform.php +++ /dev/null @@ -1,62 +0,0 @@ - - -

Waveform

- -
-
- - -
-
- - - Hz -
-
- Load -
-
- -
-
-
- - - - - - - - - - - - - - - - - -
Samples
fs
Ipeak
IRMS
-
-  ms - -
-
-
- - - - - - diff --git a/html_src/page_wifi.php b/html_src/page_wifi.php index 0ee36e3..8624f17 100644 --- a/html_src/page_wifi.php +++ b/html_src/page_wifi.php @@ -1,4 +1,5 @@ - +

Wireless Setup

diff --git a/html_src/sass/app.scss b/html_src/sass/app.scss index ac29dfa..5c8b2d1 100644 --- a/html_src/sass/app.scss +++ b/html_src/sass/app.scss @@ -6,7 +6,7 @@ @import "utils/index"; -@import "lib/chartist/chartist"; +//@import "lib/chartist/chartist"; $form-label-w: 130px; $form-label-gap: 8px; @@ -15,8 +15,8 @@ $form-field-w: 250px; $c-form-label-fg: white; $c-form-field-bg: #303030; $c-form-field-fg: white; -$c-form-highlight: #217b3a; -$c-form-highlight-a: #28bc65; +$c-form-highlight: #214e7a; +$c-form-highlight-a: #2972ba; @function dist($x) { @return modular-scale($x, 1rem, $golden); @@ -49,8 +49,6 @@ $c-form-highlight-a: #28bc65; // import all our pages @import "pages/wifi"; @import "pages/home"; -@import "pages/wfm"; -@import "pages/about"; @include media($tablet-min) { .mq-phone { display: none; } diff --git a/html_src/sass/layout/_menu.scss b/html_src/sass/layout/_menu.scss index db5b437..6c59d35 100644 --- a/html_src/sass/layout/_menu.scss +++ b/html_src/sass/layout/_menu.scss @@ -1,5 +1,5 @@ #menu { - $menu-bg: #2bab5f; + $menu-bg: #2c6cab; flex: 0 0 15rem; background: $menu-bg; @@ -51,7 +51,7 @@ font-size: 130%; color: white; - $hl: #1bd886; + $hl: #1c79d6; transition: background-color 0.2s; text-shadow: 0 0 5px rgba(black, .4); diff --git a/html_src/sass/pages/_about.scss b/html_src/sass/pages/_about.scss deleted file mode 100644 index 065c72e..0000000 --- a/html_src/sass/pages/_about.scss +++ /dev/null @@ -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; - } -} diff --git a/html_src/sass/pages/_home.scss b/html_src/sass/pages/_home.scss index 3cd6815..065c72e 100644 --- a/html_src/sass/pages/_home.scss +++ b/html_src/sass/pages/_home.scss @@ -1,11 +1,17 @@ -.page-home #staRSSIperc:after { - padding-left: dist(-4); - content: '%'; - font-size: fsize(-1); -} +.page-about { + .Box { + padding-left:dist(0); + padding-right:dist(0); + + a {font-weight: bold;} + } + + #logo { + float:right; + height: 130px; + } -.page-home #staRSSI:after { - padding-left: dist(-4); - content: 'dBm'; - font-size: fsize(-1); + #logo2 { + max-width: 150px; + } } diff --git a/html_src/sass/pages/_wfm.scss b/html_src/sass/pages/_wfm.scss deleted file mode 100644 index bb1cfdf..0000000 --- a/html_src/sass/pages/_wfm.scss +++ /dev/null @@ -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); - } - } - } -} diff --git a/html_src/x_page_layout.php b/html_src/x_page_layout.php deleted file mode 100644 index 2a47aab..0000000 --- a/html_src/x_page_layout.php +++ /dev/null @@ -1,71 +0,0 @@ - - -

Heading sdfsd sdfsd

- -
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.
- -
This is a wide box for like a graph or whatever.
- 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!
- -
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!
- -
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur ex rerum tempore voluptates? Accusamus corporis, dolorem enim This is a link. ipsum molestiae molestias non odit perspiciatis repellendus sint, soluta, tempore tenetur vitae voluptate!
- - -
-
-
- - -
-
-
- -
-
- - -
-
- - -
-
- - -
-
-
- - -
-
-
- -
-
- - -
-
-
- - - -
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!
- -
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!
- -
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!
- -
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!
- -
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!
- - diff --git a/libesphttpd/core/auth.c b/libesphttpd/core/auth.c index e244a44..bff7f77 100644 --- a/libesphttpd/core/auth.c +++ b/libesphttpd/core/auth.c @@ -5,9 +5,9 @@ HTTP auth implementation. Only does basic authentication for now. /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): - * Jeroen Domburg wrote this file. As long as you retain - * this notice you can do whatever you want with this stuff. If we meet some day, - * and you think this stuff is worth it, you can buy me a beer in return. + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. * ---------------------------------------------------------------------------- */ @@ -16,7 +16,7 @@ HTTP auth implementation. Only does basic authentication for now. #include "auth.h" #include "base64.h" -int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) { +httpd_cgi_state authBasic(HttpdConnData *connData) { const char *forbidden="401 Forbidden."; int no=0; int r; diff --git a/libesphttpd/include/auth.h b/libesphttpd/include/auth.h index 132f6d5..8636fd0 100644 --- a/libesphttpd/include/auth.h +++ b/libesphttpd/include/auth.h @@ -18,6 +18,6 @@ //has. typedef int (* AuthGetUserPw)(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen); -int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData); +httpd_cgi_state ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData); #endif diff --git a/libesphttpd/include/esp8266.h b/libesphttpd/include/esp8266.h index 784a2f4..ac8ff86 100644 --- a/libesphttpd/include/esp8266.h +++ b/libesphttpd/include/esp8266.h @@ -5,6 +5,7 @@ #include #include #include +//#include "espmissingprotos.h" #ifdef FREERTOS #include @@ -35,7 +36,6 @@ #include "platform.h" -#include "espmissingprotos.h" #include "esp_sdk_ver.h" #include "logging.h" diff --git a/libesphttpd/include/logging.h b/libesphttpd/include/logging.h index c582520..f29e520 100644 --- a/libesphttpd/include/logging.h +++ b/libesphttpd/include/logging.h @@ -4,7 +4,7 @@ #include #include "uptime.h" -#define VERBOSE 0 +#define VERBOSE 1 // logging functions diff --git a/libesphttpd/include/platform.h b/libesphttpd/include/platform.h index d88f461..1f59b5c 100644 --- a/libesphttpd/include/platform.h +++ b/libesphttpd/include/platform.h @@ -2,6 +2,7 @@ #define PLATFORM_H #include +#include "espmissingprotos.h" #ifdef FREERTOS diff --git a/user/datalink.h b/user/datalink.h index 0b9ccb3..d5eb2b3 100644 --- a/user/datalink.h +++ b/user/datalink.h @@ -4,13 +4,8 @@ #include #include -// request to capture data... -#define DG_REQUEST_RAW 40 -#define DG_REQUEST_FFT 41 - -// reporting -#define DG_REQUEST_STORE_REF 42 // request to capture & store reference FFT -#define DG_REQUEST_COMPARE_REF 43 // request to capture FFT & compare with reference +#define DG_MOTOR_HOME 40 +#define DG_MOTOR_GOTO 41 // wifi status & control #define DG_SETMODE_AP 44 // request AP mode (AP button pressed) diff --git a/user/page_about.c b/user/page_about.c deleted file mode 100644 index 791d7fb..0000000 --- a/user/page_about.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#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; -} diff --git a/user/page_home.c b/user/page_home.c new file mode 100644 index 0000000..d7fd7fe --- /dev/null +++ b/user/page_home.c @@ -0,0 +1,23 @@ +#include +#include +#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; +} diff --git a/user/page_about.h b/user/page_home.h similarity index 53% rename from user/page_about.h rename to user/page_home.h index 4165ed1..bfacfac 100644 --- a/user/page_about.h +++ b/user/page_home.h @@ -3,6 +3,6 @@ #include -httpd_cgi_state tplAbout(HttpdConnData *connData, char *token, void **arg); +httpd_cgi_state tplHome(HttpdConnData *connData, char *token, void **arg); #endif // PAGE_ABOUT_H diff --git a/user/page_monitoring.c b/user/page_monitoring.c deleted file mode 100644 index d91f0f8..0000000 --- a/user/page_monitoring.c +++ /dev/null @@ -1,189 +0,0 @@ -#include -#include -#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; -} diff --git a/user/page_monitoring.h b/user/page_monitoring.h deleted file mode 100644 index 7449e2f..0000000 --- a/user/page_monitoring.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef PAGE_MONITORING_H -#define PAGE_MONITORING_H - -#include - -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 diff --git a/user/page_status.c b/user/page_status.c deleted file mode 100644 index 8d38561..0000000 --- a/user/page_status.c +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include -#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%" - }, -*/ diff --git a/user/page_status.h b/user/page_status.h deleted file mode 100644 index baf3351..0000000 --- a/user/page_status.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PAGE_HOME_H -#define PAGE_HOME_H - -#include - -httpd_cgi_state tplSystemStatus(HttpdConnData *connData, char *token, void **arg); - -#endif // PAGE_HOME_H diff --git a/user/page_waveform.c b/user/page_waveform.c deleted file mode 100644 index 1be65c1..0000000 --- a/user/page_waveform.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#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; -} - - - diff --git a/user/page_waveform.h b/user/page_waveform.h deleted file mode 100644 index 0c08fb0..0000000 --- a/user/page_waveform.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PAGE_WAVEFORM_H -#define PAGE_WAVEFORM_H - -#include - -httpd_cgi_state tplWaveformJSON(HttpdConnData *connData, char *token, void **arg); - -httpd_cgi_state tplFourierJSON(HttpdConnData *connData, char *token, void **arg); - -#endif // PAGE_WAVEFORM_H diff --git a/user/pers_cfg.c b/user/pers_cfg.c new file mode 100644 index 0000000..dab1aee --- /dev/null +++ b/user/pers_cfg.c @@ -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."); +} diff --git a/user/pers_cfg.h b/user/pers_cfg.h new file mode 100644 index 0000000..576a500 --- /dev/null +++ b/user/pers_cfg.h @@ -0,0 +1,23 @@ +#ifndef REPORTING_H +#define REPORTING_H + +#include + +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 diff --git a/user/reporting.c b/user/reporting.c deleted file mode 100644 index 07430fb..0000000 --- a/user/reporting.c +++ /dev/null @@ -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; -} diff --git a/user/reporting.h b/user/reporting.h deleted file mode 100644 index 64a743a..0000000 --- a/user/reporting.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef REPORTING_H -#define REPORTING_H - -#include - -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 diff --git a/user/routes.c b/user/routes.c index 01141c4..dde6827 100644 --- a/user/routes.c +++ b/user/routes.c @@ -6,18 +6,15 @@ #include "httpdespfs.h" #include "cgiwifi.h" //#include "cgiflash.h" -//#include "auth.h" +#include "auth.h" //#include "cgiwebsocket.h" // user files -#include "page_status.h" -#include "page_waveform.h" -#include "page_about.h" -#include "page_monitoring.h" +#include "page_home.h" #include "cgi_reset.h" #include "cgi_ping.h" -#define WIFI_PROTECT 0 +#define WIFI_PROTECT 1 #if WIFI_PROTECT static int FLASH_FN myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen); @@ -41,26 +38,12 @@ HttpdBuiltInUrl builtInUrls[] = { // --- System control --- ROUTE_CGI("/system/reset", cgiResetDevice), ROUTE_CGI("/system/ping", cgiPing), - ROUTE_TPL_FILE("/system/status", tplSystemStatus, "/json/status.tpl"), - - // --- Measurement --- - ROUTE_TPL_FILE("/measure/raw", tplWaveformJSON, "/json/samples.tpl"), - ROUTE_TPL_FILE("/measure/fft", tplFourierJSON, "/json/samples.tpl"), - - ROUTE_CGI("/mon/compare", cgiMonCompare), - ROUTE_CGI("/mon/status", cgiMonStatus), - ROUTE_CGI("/mon/setref", cgiMonSetRef), - ROUTE_CGI("/mon/config", cgiMonitoringCfg), // redirects to /monitoring // --- UI pages --- // System Status page - ROUTE_TPL_FILE("/", tplSystemStatus, "/pages/status.tpl"), - ROUTE_TPL_FILE("/status", tplSystemStatus, "/pages/status.tpl"), - ROUTE_TPL_FILE("/about", tplAbout, "/pages/about.tpl"), - ROUTE_TPL_FILE("/monitoring", tplMonitoring, "/pages/monitoring.tpl"), - ROUTE_FILE("/waveform", "/pages/wfm.html"), // static file, html -> can use gzip - ROUTE_FILE("/fft", "/pages/fft.html"), // static file, html -> can use gzip - ROUTE_FILE("/spectrogram", "/pages/sgm.html"), // static file, html -> can use gzip + ROUTE_REDIRECT("/", "/home"), + ROUTE_REDIRECT("/home/", "/home"), + ROUTE_TPL_FILE("/home", tplHome, "/pages/home.tpl"), // --- WiFi config --- #if WIFI_PROTECT @@ -104,8 +87,8 @@ static int FLASH_FN myPassFn(HttpdConnData *connData, int no, char *user, int us (void)passLen; if (no == 0) { - os_strcpy(user, "admin"); - os_strcpy(pass, "s3cr3t"); + os_strcpy(user, "wifiadmin"); + os_strcpy(pass, "amazing grace"); return 1; //Add more users this way. Check against incrementing no for each user added. // } else if (no==1) { diff --git a/user/sampling.c b/user/sampling.c deleted file mode 100644 index fad15c2..0000000 --- a/user/sampling.c +++ /dev/null @@ -1,277 +0,0 @@ -#include -#include - -#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; -} diff --git a/user/sampling.h b/user/sampling.h deleted file mode 100644 index 59ea239..0000000 --- a/user/sampling.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef SAMPLING_H -#define SAMPLING_H - -#include -#include -#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 diff --git a/user/sbmp_config.h b/user/sbmp_config.h index 651ad10..ed00d91 100644 --- a/user/sbmp_config.h +++ b/user/sbmp_config.h @@ -55,7 +55,7 @@ /** * @brief Enable detailed logging (only for debugging, disable for better performance). */ -#define SBMP_DEBUG 0 +#define SBMP_DEBUG 1 // here are the actual logging functions diff --git a/user/user_main.c b/user/user_main.c index e6c78bc..c849f6b 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -23,7 +23,7 @@ #include "routes.h" #include "fw_version.h" -#include "reporting.h" +#include "pers_cfg.h" #include "wificontrol.h" extern HttpdBuiltInUrl builtInUrls[]; @@ -84,7 +84,7 @@ void user_init(void) serialInit(); uptime_timer_init(); - banner("*** AC current analyser - WiFi module ***"); + banner("*** WiFi Demo - Stepper motor control ***"); banner_info("(c) Ondrej Hruska, 2016"); banner_info("Katedra mereni FEL CVUT"); banner_info(""); @@ -95,6 +95,12 @@ void user_init(void) // reset button etc ioInit(); + struct softap_config wificfg; + wifi_softap_get_config(&wificfg); + sprintf((char*)wificfg.ssid, "esp_motor_demo"); + wificfg.ssid_len = strlen((char*)wificfg.ssid); + wifi_softap_set_config(&wificfg); + // set up SBMP datalinkInit(); @@ -113,8 +119,7 @@ void user_init(void) httpdInit(builtInUrls, 80); - // start reporting timer - reporting_cfg_load(); + persistent_cfg_load(); printf(LOG_EOL); banner_info("Ready"); diff --git a/user/wificontrol.c b/user/wificontrol.c index f0f80de..873dfae 100644 --- a/user/wificontrol.c +++ b/user/wificontrol.c @@ -3,7 +3,7 @@ #include "wificontrol.h" #include #include "datalink.h" -#include "reporting.h" +#include "pers_cfg.h" // --- AP --- @@ -95,6 +95,11 @@ static void FLASH_FN wifistatus_cb(void *arg) { (void)arg; + if (sbmp_ep_handshake_status(dlnk_ep) != SBMP_HSK_SUCCESS) { + warn("SBMP hsk not success, can't send WiFi status!"); + return; + } + WIFI_MODE opmode = wifi_get_opmode(); STATION_STATUS status = STATION_IDLE; @@ -102,11 +107,10 @@ static void FLASH_FN wifistatus_cb(void *arg) status = wifi_station_get_connect_status(); } - if (sbmp_ep_start_message(dlnk_ep, DG_WIFI_STATUS, 4, NULL)) { + if (sbmp_ep_start_message(dlnk_ep, DG_WIFI_STATUS, 3, NULL)) { sbmp_ep_send_u8(dlnk_ep, opmode); // 1-Client, 2-SoftAP, 3-STA+AP sbmp_ep_send_u8(dlnk_ep, status == STATION_GOT_IP); // Station connected sbmp_ep_send_u8(dlnk_ep, wps_in_progress); // 1 = WPS is in progress - sbmp_ep_send_u8(dlnk_ep, rpt_conf.enabled); // Reporting is enabled } }