diff --git a/.gitignore b/.gitignore
index f91ec08..1708808 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,7 @@
*.swp
*.pyc
*.log
-js/mobile.js
-js/init_plot.js
-js/version.json
-css/mobile.css
-cache.manifest
-tiles/
\ No newline at end of file
+/index.html
+/service-worker.js
+/js/version.json
+tiles/
diff --git a/.htaccess b/.htaccess
deleted file mode 100644
index 3d763d3..0000000
--- a/.htaccess
+++ /dev/null
@@ -1,38 +0,0 @@
-
- # Compress HTML, CSS, JavaScript, Text, XML and fonts
- AddOutputFilterByType DEFLATE application/javascript
- AddOutputFilterByType DEFLATE application/rss+xml
- AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
- AddOutputFilterByType DEFLATE application/x-font
- AddOutputFilterByType DEFLATE application/x-font-opentype
- AddOutputFilterByType DEFLATE application/x-font-otf
- AddOutputFilterByType DEFLATE application/x-font-truetype
- AddOutputFilterByType DEFLATE application/x-font-ttf
- AddOutputFilterByType DEFLATE application/x-javascript
- AddOutputFilterByType DEFLATE application/xhtml+xml
- AddOutputFilterByType DEFLATE application/xml
- AddOutputFilterByType DEFLATE font/opentype
- AddOutputFilterByType DEFLATE font/otf
- AddOutputFilterByType DEFLATE font/ttf
- AddOutputFilterByType DEFLATE image/svg+xml
- AddOutputFilterByType DEFLATE image/x-icon
- AddOutputFilterByType DEFLATE text/css
- AddOutputFilterByType DEFLATE text/html
- AddOutputFilterByType DEFLATE text/javascript
- AddOutputFilterByType DEFLATE text/plain
- AddOutputFilterByType DEFLATE text/xml
-
- # Remove browser bugs (only needed for ancient browsers)
- BrowserMatch ^Mozilla/4 gzip-only-text/html
- BrowserMatch ^Mozilla/4\.0[678] no-gzip
- BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
- Header append Vary User-Agent
-
-
-AddType text/cache-manifest .manifest
-AddType text/cache-manifest .appcache
-
-AddType application/x-font-woff .woff
-AddType application/x-font-ttf .ttf
-AddType application/vnd.ms-fontobject .eot
-AddType image/svg+xml .svg
diff --git a/DEVELOPER_README.md b/DEVELOPER_README.md
index 3272308..6f38d04 100644
--- a/DEVELOPER_README.md
+++ b/DEVELOPER_README.md
@@ -4,6 +4,6 @@ To get a copy of the code and run a test web server:
1. [Fork the repository](https://github.com/projecthorus/sondehub-tracker/fork) by visiting [https://github.com/projecthorus/sondehub-tracker/fork](https://github.com/projecthorus/sondehub-tracker/fork).
2. Clone the repository with your git tool of choice.
-3. Run `build.sh` to compile the javascript files. (This requires Java to be installed and in your path.)
+3. Run `build.sh` to generate `index.html`, `service-worker.js`, and `js/version.json`.
4. Run `python serve.py` to run a simple web server to (This requires python 3.x)
5. Visit [http://localhost:8000](http://localhost:8000) to view the local version of the server!
diff --git a/Dockerfile b/Dockerfile
index fbb1bdb..53107d5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
FROM alpine:latest
-RUN apk add --no-cache python3 openjdk11 sed git
+RUN apk add --no-cache python3 sed git
WORKDIR /app
ADD . .
diff --git a/README.md b/README.md
index 2a812de..42427be 100644
--- a/README.md
+++ b/README.md
@@ -36,8 +36,6 @@ Pull requests are welcome.
## Installation
-Requirements: Java
-
$ git clone https://github.com/projecthorus/sondehub-tracker.git
$ ./build.sh
$ python serve.py
diff --git a/build.sh b/build.sh
index ecabd0e..948cde1 100755
--- a/build.sh
+++ b/build.sh
@@ -1,50 +1,22 @@
#!/bin/bash
-# compile stylesheet
-echo -n "Compiling CSS... "
-cd css
-rm -f mobile.css
-cat base.css skeleton.css layout.css habitat-font.css main.css leaflet.css leaflet.fullscreen.css skewt.css > mobile.tmp
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=css mobile.tmp > mobile.css
-rm -f mobile.tmp
-cd ..
-echo "Done!"
-
-#compile javascript
-echo -n "Compiling JavaScript... "
-cd js
-rm -f mobile.js init_plot.js
-# precompiled libs
-cat jquery* >> mobile.js
+set -e
VERSION="`git rev-parse --short HEAD`"
-
BUILD_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"
-# compile the rest
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge iscroll.js >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge chasecar.lib.js | sed "s/{VER}/$VERSION/" >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge tracker.js >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge app.js | sed "s/{VER}/$VERSION/" | sed "s/{BUILD_DATE}/$BUILD_DATE/" >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge colour-map.js >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge xdata.js >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge station.js >> mobile.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge format.js >> mobile.js
-
-#compile plot lib and config
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge _jquery.flot.js >> init_plot.js
-java -jar "../tools/yuicompressor-2.4.8.jar" --type=js --disable-optimizations --nomunge plot_config.js >> init_plot.js
-
# create version check file
-echo "{\"build_date\": \"$BUILD_DATE\", \"version\": \"$VERSION\", \"refresh\": 86400}" > version.json
-
-cd ..
+echo -n "Generating js/version.json... "
+echo "{\"build_date\": \"$BUILD_DATE\", \"version\": \"$VERSION\", \"refresh\": 86400}" > js/version.json
echo "Done!"
# cache fixes
-sed -i'' "s/{VER}/$VERSION/" index.html
-sed -i'' "s/{VER}/$VERSION/" service-worker.js
+echo -n "Generating index.html... "
+sed -e "s/{VER}/$VERSION/" -e "s/{BUILD_DATE}/$BUILD_DATE/" index.template.html > index.html
+echo "Done!"
+echo -n "Generating service-worker.js... "
+sed -e "s/{VER}/$VERSION/" service-worker.template.js > service-worker.js
echo "Done!"
echo "Build version: $VERSION Build date: $BUILD_DATE"
diff --git a/css/base.css b/css/base.css
index 8c20088..016fe3e 100644
--- a/css/base.css
+++ b/css/base.css
@@ -29,257 +29,572 @@
/* #Reset & Basics (Inspired by E. Meyers)
================================================== */
- html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline; }
- sup {
- font-size: smaller;
- vertical-align: +0.4em; }
- sub {
- font-size: smaller;
- vertical-align: -0.25em; }
- article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
- display: block; }
- body {
- line-height: 1; }
- ol, ul {
- list-style: none; }
- blockquote, q {
- quotes: none; }
- blockquote:before, blockquote:after,
- q:before, q:after {
- content: '';
- content: none; }
- table {
- border-collapse: collapse;
- border-spacing: 0; }
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+
+sup {
+ font-size: smaller;
+ vertical-align: +0.4em;
+}
+
+sub {
+ font-size: smaller;
+ vertical-align: -0.25em;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+ display: block;
+}
+
+body {
+ line-height: 1;
+}
+
+ol,
+ul {
+ list-style: none;
+}
+
+blockquote,
+q {
+ quotes: none;
+}
+
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+ content: '';
+ content: none;
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
/* #Basic Styles
================================================== */
- body {
- background: #fff;
- font: 14px/21px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
- color: #666;
- -webkit-font-smoothing: antialiased; /* Fix for webkit rendering */
- -webkit-text-size-adjust: 100%;
- }
+body {
+ background: #fff;
+ font: 14px/21px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #666;
+ -webkit-font-smoothing: antialiased;
+ /* Fix for webkit rendering */
+ -webkit-text-size-adjust: 100%;
+}
/* #Typography
================================================== */
- h1, h2, h3, h4, h5, h6 {
- font-weight: normal; }
- h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
- h1 { font-size: 46px; line-height: 50px; margin-bottom: 14px;}
- h2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; }
- h3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; }
- h4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; }
- h5 { font-size: 17px; line-height: 24px; }
- h6 { font-size: 14px; line-height: 21px; }
- .subheader { color: #777; }
-
- p { margin: 0 0 20px 0; }
- p img { margin: 0; }
- p.lead { font-size: 21px; line-height: 27px; color: #777; }
-
- em { font-style: italic; }
- strong { font-weight: bold; color: #333; }
- b { font-weight: bold; }
- small { font-size: 80%; }
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-weight: normal;
+}
+
+h1 a,
+h2 a,
+h3 a,
+h4 a,
+h5 a,
+h6 a {
+ font-weight: inherit;
+}
+
+h1 {
+ font-size: 46px;
+ line-height: 50px;
+ margin-bottom: 14px;
+}
+
+h2 {
+ font-size: 35px;
+ line-height: 40px;
+ margin-bottom: 10px;
+}
+
+h3 {
+ font-size: 28px;
+ line-height: 34px;
+ margin-bottom: 8px;
+}
+
+h4 {
+ font-size: 21px;
+ line-height: 30px;
+ margin-bottom: 4px;
+}
+
+h5 {
+ font-size: 17px;
+ line-height: 24px;
+}
+
+h6 {
+ font-size: 14px;
+ line-height: 21px;
+}
+
+.subheader {
+ color: #777;
+}
+
+p {
+ margin: 0 0 20px 0;
+}
+
+p img {
+ margin: 0;
+}
+
+p.lead {
+ font-size: 21px;
+ line-height: 27px;
+ color: #777;
+}
+
+em {
+ font-style: italic;
+}
+
+strong {
+ font-weight: bold;
+ color: #333;
+}
+
+b {
+ font-weight: bold;
+}
+
+small {
+ font-size: 80%;
+}
/* Blockquotes */
- blockquote, blockquote p { font-size: 17px; line-height: 24px; color: #777; font-style: italic; }
- blockquote { margin: 0 0 20px; padding: 9px 20px 0 19px; border-left: 1px solid #ddd; }
- blockquote cite { display: block; font-size: 12px; color: #555; }
- blockquote cite:before { content: "\2014 \0020"; }
- blockquote cite a, blockquote cite a:visited, blockquote cite a:visited { color: #555; }
-
- hr { border: solid #ddd; border-width: 1px 0 0; clear: both; height: 0; }
+blockquote,
+blockquote p {
+ font-size: 17px;
+ line-height: 24px;
+ color: #777;
+ font-style: italic;
+}
+
+blockquote {
+ margin: 0 0 20px;
+ padding: 9px 20px 0 19px;
+ border-left: 1px solid #ddd;
+}
+
+blockquote cite {
+ display: block;
+ font-size: 12px;
+ color: #555;
+}
+
+blockquote cite:before {
+ content: "\2014 \0020";
+}
+
+blockquote cite a,
+blockquote cite a:visited,
+blockquote cite a:visited {
+ color: #555;
+}
+
+hr {
+ border: solid #ddd;
+ border-width: 1px 0 0;
+ clear: both;
+ height: 0;
+}
/* #Links
================================================== */
- a, a:visited { color: #333; text-decoration: underline; outline: 0; }
- a:hover, a:focus { color: #000; }
- p a, p a:visited { line-height: inherit; }
+a,
+a:visited {
+ color: #333;
+ text-decoration: underline;
+ outline: 0;
+}
+
+a:hover,
+a:focus {
+ color: #000;
+}
+
+p a,
+p a:visited {
+ line-height: inherit;
+}
/* #Lists
================================================== */
- ul, ol { margin-bottom: 20px; }
- ul { list-style: none outside; }
- ol { list-style: decimal; }
- ol, ul.square, ul.circle, ul.disc { margin-left: 30px; }
- ul.square { list-style: square outside; }
- ul.circle { list-style: circle outside; }
- ul.disc { list-style: disc outside; }
- ul ul, ul ol,
- ol ol, ol ul { margin: 4px 0 5px 30px; font-size: 90%; }
- ul ul li, ul ol li,
- ol ol li, ol ul li { margin-bottom: 6px; }
- li { line-height: 18px; margin-bottom: 12px; }
- ul.large li { line-height: 21px; }
- li p { line-height: 21px; }
+ul,
+ol {
+ margin-bottom: 20px;
+}
+
+ul {
+ list-style: none outside;
+}
+
+ol {
+ list-style: decimal;
+}
+
+ol,
+ul.square,
+ul.circle,
+ul.disc {
+ margin-left: 30px;
+}
+
+ul.square {
+ list-style: square outside;
+}
+
+ul.circle {
+ list-style: circle outside;
+}
+
+ul.disc {
+ list-style: disc outside;
+}
+
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin: 4px 0 5px 30px;
+ font-size: 90%;
+}
+
+ul ul li,
+ul ol li,
+ol ol li,
+ol ul li {
+ margin-bottom: 6px;
+}
+
+li {
+ line-height: 18px;
+ margin-bottom: 12px;
+}
+
+ul.large li {
+ line-height: 21px;
+}
+
+li p {
+ line-height: 21px;
+}
/* #Images
================================================== */
- img.scale-with-grid {
- max-width: 100%;
- height: auto; }
+img.scale-with-grid {
+ max-width: 100%;
+ height: auto;
+}
/* #Buttons
================================================== */
- .button,
- button,
- input[type="submit"],
- input[type="reset"],
- input[type="button"] {
- background: #eee; /* Old browsers */
- background: #eee -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */
- background: #eee -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */
- background: #eee -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */
- background: #eee -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */
- background: #eee -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */
- background: #eee linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */
- border: 1px solid #aaa;
- border-top: 1px solid #ccc;
- border-left: 1px solid #ccc;
- margin-right: 1px;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
- color: #444;
- display: inline-block;
- font-size: 11px;
- font-weight: bold;
- text-decoration: none;
- text-shadow: 0 1px rgba(255, 255, 255, .75);
- cursor: pointer;
- line-height: normal;
- padding: 8px 10px;
- font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; }
-
- .button:hover,
- button:hover,
- input[type="submit"]:hover,
- input[type="reset"]:hover,
- input[type="button"]:hover {
- color: #222;
- background: #ddd; /* Old browsers */
- background: #ddd -moz-linear-gradient(top, rgba(255,255,255,.3) 0%, rgba(0,0,0,.3) 100%); /* FF3.6+ */
- background: #ddd -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.3)), color-stop(100%,rgba(0,0,0,.3))); /* Chrome,Safari4+ */
- background: #ddd -webkit-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Chrome10+,Safari5.1+ */
- background: #ddd -o-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Opera11.10+ */
- background: #ddd -ms-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* IE10+ */
- background: #ddd linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* W3C */
- border: 1px solid #888;
- border-top: 1px solid #aaa;
- border-left: 1px solid #aaa; }
-
- .button:active,
- button:active,
- input[type="submit"]:active,
- input[type="reset"]:active,
- input[type="button"]:active {
- border: 1px solid #666;
- background: #ccc; /* Old browsers */
- background: #ccc -moz-linear-gradient(top, rgba(255,255,255,.35) 0%, rgba(10,10,10,.4) 100%); /* FF3.6+ */
- background: #ccc -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.35)), color-stop(100%,rgba(10,10,10,.4))); /* Chrome,Safari4+ */
- background: #ccc -webkit-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Chrome10+,Safari5.1+ */
- background: #ccc -o-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Opera11.10+ */
- background: #ccc -ms-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* IE10+ */
- background: #ccc linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* W3C */ }
-
- .button.full-width,
- button.full-width,
- input[type="submit"].full-width,
- input[type="reset"].full-width,
- input[type="button"].full-width {
- width: 100%;
- padding-left: 0 !important;
- padding-right: 0 !important;
- text-align: center; }
-
- /* Fix for odd Mozilla border & padding issues */
- button::-moz-focus-inner,
- input::-moz-focus-inner {
- border: 0;
- padding: 0;
- }
-
- .button.disabled,
- button.disabled,
- input[type="submit"].disabled,
- input[type="reset"].disabled,
- input[type="button"].disabled {
- border: 1px solid #aaa;
- color: #aaa;
- background: #fff;
- }
+.button,
+button,
+input[type="submit"],
+input[type="reset"],
+input[type="button"] {
+ background: #eee;
+ /* Old browsers */
+ background: #eee -moz-linear-gradient(top, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .2) 100%);
+ /* FF3.6+ */
+ background: #eee -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(255, 255, 255, .2)), color-stop(100%, rgba(0, 0, 0, .2)));
+ /* Chrome,Safari4+ */
+ background: #eee -webkit-linear-gradient(top, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .2) 100%);
+ /* Chrome10+,Safari5.1+ */
+ background: #eee -o-linear-gradient(top, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .2) 100%);
+ /* Opera11.10+ */
+ background: #eee -ms-linear-gradient(top, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .2) 100%);
+ /* IE10+ */
+ background: #eee linear-gradient(top, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .2) 100%);
+ /* W3C */
+ border: 1px solid #aaa;
+ border-top: 1px solid #ccc;
+ border-left: 1px solid #ccc;
+ margin-right: 1px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ color: #444;
+ display: inline-block;
+ font-size: 11px;
+ font-weight: bold;
+ text-decoration: none;
+ text-shadow: 0 1px rgba(255, 255, 255, .75);
+ cursor: pointer;
+ line-height: normal;
+ padding: 8px 10px;
+ font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+.button:hover,
+button:hover,
+input[type="submit"]:hover,
+input[type="reset"]:hover,
+input[type="button"]:hover {
+ color: #222;
+ background: #ddd;
+ /* Old browsers */
+ background: #ddd -moz-linear-gradient(top, rgba(255, 255, 255, .3) 0%, rgba(0, 0, 0, .3) 100%);
+ /* FF3.6+ */
+ background: #ddd -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(255, 255, 255, .3)), color-stop(100%, rgba(0, 0, 0, .3)));
+ /* Chrome,Safari4+ */
+ background: #ddd -webkit-linear-gradient(top, rgba(255, 255, 255, .3) 0%, rgba(0, 0, 0, .3) 100%);
+ /* Chrome10+,Safari5.1+ */
+ background: #ddd -o-linear-gradient(top, rgba(255, 255, 255, .3) 0%, rgba(0, 0, 0, .3) 100%);
+ /* Opera11.10+ */
+ background: #ddd -ms-linear-gradient(top, rgba(255, 255, 255, .3) 0%, rgba(0, 0, 0, .3) 100%);
+ /* IE10+ */
+ background: #ddd linear-gradient(top, rgba(255, 255, 255, .3) 0%, rgba(0, 0, 0, .3) 100%);
+ /* W3C */
+ border: 1px solid #888;
+ border-top: 1px solid #aaa;
+ border-left: 1px solid #aaa;
+}
+
+.button:active,
+button:active,
+input[type="submit"]:active,
+input[type="reset"]:active,
+input[type="button"]:active {
+ border: 1px solid #666;
+ background: #ccc;
+ /* Old browsers */
+ background: #ccc -moz-linear-gradient(top, rgba(255, 255, 255, .35) 0%, rgba(10, 10, 10, .4) 100%);
+ /* FF3.6+ */
+ background: #ccc -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(255, 255, 255, .35)), color-stop(100%, rgba(10, 10, 10, .4)));
+ /* Chrome,Safari4+ */
+ background: #ccc -webkit-linear-gradient(top, rgba(255, 255, 255, .35) 0%, rgba(10, 10, 10, .4) 100%);
+ /* Chrome10+,Safari5.1+ */
+ background: #ccc -o-linear-gradient(top, rgba(255, 255, 255, .35) 0%, rgba(10, 10, 10, .4) 100%);
+ /* Opera11.10+ */
+ background: #ccc -ms-linear-gradient(top, rgba(255, 255, 255, .35) 0%, rgba(10, 10, 10, .4) 100%);
+ /* IE10+ */
+ background: #ccc linear-gradient(top, rgba(255, 255, 255, .35) 0%, rgba(10, 10, 10, .4) 100%);
+ /* W3C */
+}
+
+.button.full-width,
+button.full-width,
+input[type="submit"].full-width,
+input[type="reset"].full-width,
+input[type="button"].full-width {
+ width: 100%;
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+ text-align: center;
+}
+
+/* Fix for odd Mozilla border & padding issues */
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+.button.disabled,
+button.disabled,
+input[type="submit"].disabled,
+input[type="reset"].disabled,
+input[type="button"].disabled {
+ border: 1px solid #aaa;
+ color: #aaa;
+ background: #fff;
+}
/* #Forms
================================================== */
- fieldset {
- margin-bottom: 20px; }
- input[type="text"],
- input[type="password"],
- input[type="email"],
- textarea,
- select {
- border: 1px solid #ccc;
- padding: 6px 4px;
- outline: none;
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- font: 13px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
- color: #888;
- margin: 0;
- max-width: 100%;
- background: #fff; }
- select {
- padding: 0; }
- input[type="text"]:focus,
- input[type="password"]:focus,
- input[type="email"]:focus,
- textarea:focus {
- border: 1px solid #aaa;
- color: #444;
- -moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
- -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
- box-shadow: 0 0 3px rgba(0,0,0,.2); }
- textarea {
- min-height: 60px; }
- label,
- legend {
- display: block;
- font-weight: bold;
- font-size: 13px; }
- select {
- width: 220px; }
- input[type="checkbox"] {
- display: inline; }
- label span,
- legend span {
- font-weight: normal;
- font-size: 13px;
- color: #444; }
+fieldset {
+ margin-bottom: 20px;
+}
+
+input[type="text"],
+input[type="password"],
+input[type="email"],
+textarea,
+select {
+ border: 1px solid #ccc;
+ padding: 6px 4px;
+ outline: none;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ font: 13px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #888;
+ margin: 0;
+ max-width: 100%;
+ background: #fff;
+}
+
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="email"]:focus,
+textarea:focus {
+ border: 1px solid #aaa;
+ color: #444;
+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, .2);
+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .2);
+ box-shadow: 0 0 3px rgba(0, 0, 0, .2);
+}
+
+textarea {
+ min-height: 60px;
+}
+
+label,
+legend {
+ display: block;
+ font-weight: bold;
+ font-size: 13px;
+}
+
+select {
+ width: 220px;
+}
+
+input[type="checkbox"] {
+ display: inline;
+}
+
+label span,
+legend span {
+ font-weight: normal;
+ font-size: 13px;
+ color: #444;
+}
/* #Misc
================================================== */
- .remove-bottom { margin-bottom: 0 !important; }
- .half-bottom { margin-bottom: 10px !important; }
- .add-bottom { margin-bottom: 20px !important; }
- .no-margin { margin: 0 !important; padding: 0; }
-
-
+.remove-bottom {
+ margin-bottom: 0 !important;
+}
+
+.half-bottom {
+ margin-bottom: 10px !important;
+}
+
+.add-bottom {
+ margin-bottom: 20px !important;
+}
+
+.no-margin {
+ margin: 0 !important;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/css/layout.css b/css/layout.css
index 2b915f2..8ebfd8f 100644
--- a/css/layout.css
+++ b/css/layout.css
@@ -179,4 +179,20 @@ header h1{
padding: 10px;
border-width: 1px;
display: none;
+}
+
+#banner {
+ display: none
+}
+@media only screen and (min-width: 768px){
+ #banner {
+ line-height: 1.1;
+ font-size: small;
+ display: block;
+ margin-left: 300px;
+ text-align: center;
+ overflow-y: auto;
+ font-weight: bold;
+ height: 100%;
+ }
}
\ No newline at end of file
diff --git a/css/main.css b/css/main.css
index e273a77..ee57d7f 100644
--- a/css/main.css
+++ b/css/main.css
@@ -99,11 +99,13 @@ body {
#timebox {
top: 7px;
right: 5px;
+ width: 205px;
}
#lookanglesbox {
top: 40px;
right: 5px;
+ width: 205px;
}
#timebox.past svg path {
diff --git a/img/apple-touch-icon.png b/img/apple-touch-icon.png
index b16c0d7..380f8a3 100644
Binary files a/img/apple-touch-icon.png and b/img/apple-touch-icon.png differ
diff --git a/img/graw_logo_small.png b/img/graw_logo_small.png
index 4d1043e..dedb4f3 100644
Binary files a/img/graw_logo_small.png and b/img/graw_logo_small.png differ
diff --git a/img/icons/icon_x192.png b/img/icons/icon_x192.png
index 618ae3a..bcf4bac 100644
Binary files a/img/icons/icon_x192.png and b/img/icons/icon_x192.png differ
diff --git a/img/icons/icon_x512.png b/img/icons/icon_x512.png
index 9654aad..5795d0f 100644
Binary files a/img/icons/icon_x512.png and b/img/icons/icon_x512.png differ
diff --git a/img/icons/maskable_icon_x128.png b/img/icons/maskable_icon_x128.png
index ed395e1..1101d10 100644
Binary files a/img/icons/maskable_icon_x128.png and b/img/icons/maskable_icon_x128.png differ
diff --git a/img/icons/maskable_icon_x192.png b/img/icons/maskable_icon_x192.png
index 1ec5586..87b550d 100644
Binary files a/img/icons/maskable_icon_x192.png and b/img/icons/maskable_icon_x192.png differ
diff --git a/img/icons/maskable_icon_x384.png b/img/icons/maskable_icon_x384.png
index ef558c9..31c9d5c 100644
Binary files a/img/icons/maskable_icon_x384.png and b/img/icons/maskable_icon_x384.png differ
diff --git a/img/icons/maskable_icon_x48.png b/img/icons/maskable_icon_x48.png
index 56ae4a7..dad2250 100644
Binary files a/img/icons/maskable_icon_x48.png and b/img/icons/maskable_icon_x48.png differ
diff --git a/img/icons/maskable_icon_x512.png b/img/icons/maskable_icon_x512.png
index f00d755..8dff53a 100644
Binary files a/img/icons/maskable_icon_x512.png and b/img/icons/maskable_icon_x512.png differ
diff --git a/img/icons/maskable_icon_x72.png b/img/icons/maskable_icon_x72.png
index 1388186..34e3a9e 100644
Binary files a/img/icons/maskable_icon_x72.png and b/img/icons/maskable_icon_x72.png differ
diff --git a/img/icons/maskable_icon_x96.png b/img/icons/maskable_icon_x96.png
index febd7c0..4d7b7a3 100644
Binary files a/img/icons/maskable_icon_x96.png and b/img/icons/maskable_icon_x96.png differ
diff --git a/img/logo.png b/img/logo.png
deleted file mode 100644
index cc06274..0000000
Binary files a/img/logo.png and /dev/null differ
diff --git a/img/markers/balloon-adafruit.png b/img/markers/balloon-adafruit.png
deleted file mode 100644
index 4c715f2..0000000
Binary files a/img/markers/balloon-adafruit.png and /dev/null differ
diff --git a/img/markers/balloon-blue.png b/img/markers/balloon-blue.png
deleted file mode 100644
index 9888487..0000000
Binary files a/img/markers/balloon-blue.png and /dev/null differ
diff --git a/img/markers/balloon-buzz.png b/img/markers/balloon-buzz.png
deleted file mode 100644
index 17097b5..0000000
Binary files a/img/markers/balloon-buzz.png and /dev/null differ
diff --git a/img/markers/balloon-cyan.png b/img/markers/balloon-cyan.png
deleted file mode 100644
index 9eae707..0000000
Binary files a/img/markers/balloon-cyan.png and /dev/null differ
diff --git a/img/markers/balloon-green.png b/img/markers/balloon-green.png
deleted file mode 100644
index 126a0b0..0000000
Binary files a/img/markers/balloon-green.png and /dev/null differ
diff --git a/img/markers/balloon-invisible.png b/img/markers/balloon-invisible.png
deleted file mode 100644
index 19464e9..0000000
Binary files a/img/markers/balloon-invisible.png and /dev/null differ
diff --git a/img/markers/balloon-iss.png b/img/markers/balloon-iss.png
deleted file mode 100644
index 23d2a49..0000000
Binary files a/img/markers/balloon-iss.png and /dev/null differ
diff --git a/img/markers/balloon-orange.png b/img/markers/balloon-orange.png
deleted file mode 100644
index b0c5d09..0000000
Binary files a/img/markers/balloon-orange.png and /dev/null differ
diff --git a/img/markers/balloon-pop.png b/img/markers/balloon-pop.png
index cb65773..eac488b 100644
Binary files a/img/markers/balloon-pop.png and b/img/markers/balloon-pop.png differ
diff --git a/img/markers/balloon-purple.png b/img/markers/balloon-purple.png
deleted file mode 100644
index e129b1c..0000000
Binary files a/img/markers/balloon-purple.png and /dev/null differ
diff --git a/img/markers/balloon-red.png b/img/markers/balloon-red.png
deleted file mode 100644
index f079bfe..0000000
Binary files a/img/markers/balloon-red.png and /dev/null differ
diff --git a/img/markers/balloon-rob.png b/img/markers/balloon-rob.png
deleted file mode 100644
index 819a558..0000000
Binary files a/img/markers/balloon-rob.png and /dev/null differ
diff --git a/img/markers/balloon-rpi.png b/img/markers/balloon-rpi.png
deleted file mode 100644
index c340631..0000000
Binary files a/img/markers/balloon-rpi.png and /dev/null differ
diff --git a/img/markers/balloon-shockpink.png b/img/markers/balloon-shockpink.png
deleted file mode 100644
index 49ad112..0000000
Binary files a/img/markers/balloon-shockpink.png and /dev/null differ
diff --git a/img/markers/balloon-thereg.png b/img/markers/balloon-thereg.png
deleted file mode 100644
index f26068f..0000000
Binary files a/img/markers/balloon-thereg.png and /dev/null differ
diff --git a/img/markers/balloon-yellow.png b/img/markers/balloon-yellow.png
deleted file mode 100644
index 66fc042..0000000
Binary files a/img/markers/balloon-yellow.png and /dev/null differ
diff --git a/img/markers/balloon.svg b/img/markers/balloon.svg
new file mode 100755
index 0000000..8966505
--- /dev/null
+++ b/img/markers/balloon.svg
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/img/markers/car-blue.png b/img/markers/car-blue.png
deleted file mode 100644
index 09192f0..0000000
Binary files a/img/markers/car-blue.png and /dev/null differ
diff --git a/img/markers/car-green.png b/img/markers/car-green.png
deleted file mode 100644
index c42da50..0000000
Binary files a/img/markers/car-green.png and /dev/null differ
diff --git a/img/markers/car-purple.png b/img/markers/car-purple.png
deleted file mode 100644
index a281513..0000000
Binary files a/img/markers/car-purple.png and /dev/null differ
diff --git a/img/markers/car-red.png b/img/markers/car-red.png
deleted file mode 100644
index ce44c92..0000000
Binary files a/img/markers/car-red.png and /dev/null differ
diff --git a/img/markers/car-teal.png b/img/markers/car-teal.png
deleted file mode 100644
index f0e6fe8..0000000
Binary files a/img/markers/car-teal.png and /dev/null differ
diff --git a/img/markers/car-yellow.png b/img/markers/car-yellow.png
deleted file mode 100644
index 5c35476..0000000
Binary files a/img/markers/car-yellow.png and /dev/null differ
diff --git a/img/markers/car.svg b/img/markers/car.svg
new file mode 100644
index 0000000..c277ce8
--- /dev/null
+++ b/img/markers/car.svg
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/img/markers/parachute-blue.png b/img/markers/parachute-blue.png
deleted file mode 100644
index ff4dc5d..0000000
Binary files a/img/markers/parachute-blue.png and /dev/null differ
diff --git a/img/markers/parachute-cyan.png b/img/markers/parachute-cyan.png
deleted file mode 100644
index bf83a49..0000000
Binary files a/img/markers/parachute-cyan.png and /dev/null differ
diff --git a/img/markers/parachute-green.png b/img/markers/parachute-green.png
deleted file mode 100644
index f41d7e1..0000000
Binary files a/img/markers/parachute-green.png and /dev/null differ
diff --git a/img/markers/parachute-orange.png b/img/markers/parachute-orange.png
deleted file mode 100644
index e3f2d16..0000000
Binary files a/img/markers/parachute-orange.png and /dev/null differ
diff --git a/img/markers/parachute-purple.png b/img/markers/parachute-purple.png
deleted file mode 100644
index adae959..0000000
Binary files a/img/markers/parachute-purple.png and /dev/null differ
diff --git a/img/markers/parachute-red.png b/img/markers/parachute-red.png
deleted file mode 100644
index 603c60f..0000000
Binary files a/img/markers/parachute-red.png and /dev/null differ
diff --git a/img/markers/parachute-rpi.png b/img/markers/parachute-rpi.png
deleted file mode 100644
index ad421b6..0000000
Binary files a/img/markers/parachute-rpi.png and /dev/null differ
diff --git a/img/markers/parachute-yellow.png b/img/markers/parachute-yellow.png
deleted file mode 100644
index 4d85a51..0000000
Binary files a/img/markers/parachute-yellow.png and /dev/null differ
diff --git a/img/markers/parachute.svg b/img/markers/parachute.svg
new file mode 100644
index 0000000..8b10853
--- /dev/null
+++ b/img/markers/parachute.svg
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/img/markers/payload-blue.png b/img/markers/payload-blue.png
deleted file mode 100644
index c03caee..0000000
Binary files a/img/markers/payload-blue.png and /dev/null differ
diff --git a/img/markers/payload-cyan.png b/img/markers/payload-cyan.png
deleted file mode 100644
index 226bfa8..0000000
Binary files a/img/markers/payload-cyan.png and /dev/null differ
diff --git a/img/markers/payload-green.png b/img/markers/payload-green.png
deleted file mode 100644
index f524a73..0000000
Binary files a/img/markers/payload-green.png and /dev/null differ
diff --git a/img/markers/payload-orange.png b/img/markers/payload-orange.png
deleted file mode 100644
index 20e5b05..0000000
Binary files a/img/markers/payload-orange.png and /dev/null differ
diff --git a/img/markers/payload-purple.png b/img/markers/payload-purple.png
deleted file mode 100644
index 80e1e1a..0000000
Binary files a/img/markers/payload-purple.png and /dev/null differ
diff --git a/img/markers/payload-recovery-planned.png b/img/markers/payload-recovery-planned.png
new file mode 100644
index 0000000..e314714
Binary files /dev/null and b/img/markers/payload-recovery-planned.png differ
diff --git a/img/markers/payload-red.png b/img/markers/payload-red.png
deleted file mode 100644
index 7ad8acc..0000000
Binary files a/img/markers/payload-red.png and /dev/null differ
diff --git a/img/markers/payload-rpi.png b/img/markers/payload-rpi.png
deleted file mode 100644
index 9f533fb..0000000
Binary files a/img/markers/payload-rpi.png and /dev/null differ
diff --git a/img/markers/payload-yellow.png b/img/markers/payload-yellow.png
deleted file mode 100644
index e9b7bb5..0000000
Binary files a/img/markers/payload-yellow.png and /dev/null differ
diff --git a/img/markers/payload.svg b/img/markers/payload.svg
new file mode 100644
index 0000000..b89d7d6
--- /dev/null
+++ b/img/markers/payload.svg
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/img/markers/target-blue.png b/img/markers/target-blue.png
deleted file mode 100644
index fae5796..0000000
Binary files a/img/markers/target-blue.png and /dev/null differ
diff --git a/img/markers/target-cyan.png b/img/markers/target-cyan.png
deleted file mode 100644
index ba30743..0000000
Binary files a/img/markers/target-cyan.png and /dev/null differ
diff --git a/img/markers/target-green.png b/img/markers/target-green.png
deleted file mode 100644
index 56b4682..0000000
Binary files a/img/markers/target-green.png and /dev/null differ
diff --git a/img/markers/target-orange.png b/img/markers/target-orange.png
deleted file mode 100644
index 4b353b6..0000000
Binary files a/img/markers/target-orange.png and /dev/null differ
diff --git a/img/markers/target-purple.png b/img/markers/target-purple.png
deleted file mode 100644
index 4510158..0000000
Binary files a/img/markers/target-purple.png and /dev/null differ
diff --git a/img/markers/target-red.png b/img/markers/target-red.png
deleted file mode 100644
index 5987df9..0000000
Binary files a/img/markers/target-red.png and /dev/null differ
diff --git a/img/markers/target-yellow.png b/img/markers/target-yellow.png
deleted file mode 100644
index 8dc2d08..0000000
Binary files a/img/markers/target-yellow.png and /dev/null differ
diff --git a/img/markers/target.svg b/img/markers/target.svg
new file mode 100644
index 0000000..e80875e
--- /dev/null
+++ b/img/markers/target.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/img/sondehub_au.png b/img/sondehub_au.png
new file mode 100644
index 0000000..069c3c0
Binary files /dev/null and b/img/sondehub_au.png differ
diff --git a/img/sondehub_supporters.kra b/img/sondehub_supporters.kra
index 901db8e..6728b1b 100644
Binary files a/img/sondehub_supporters.kra and b/img/sondehub_supporters.kra differ
diff --git a/img/splash/splash-wide.png b/img/splash/splash-wide.png
index f5766e9..59b1fcb 100644
Binary files a/img/splash/splash-wide.png and b/img/splash/splash-wide.png differ
diff --git a/index.html b/index.template.html
similarity index 86%
rename from index.html
rename to index.template.html
index 21fb97c..964bc91 100644
--- a/index.html
+++ b/index.template.html
@@ -9,6 +9,7 @@
+
@@ -19,15 +20,42 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -56,21 +84,70 @@
no location
+
-
Recoveries
+
Report Recovery
-
Recovery reports can be added on the Chase-Car pane.
+
+ Please report recovered radiosondes! Don't waste others time and effort with a frustrating failed recovery!
+ Enter the serial number, select recovered / planned, and add some notes. If marking as planned, please add contact information!
+ If the sonde is not on the map, type its serial into the top-left search box (may require landscape mode on mobile) and press enter to retrieve historical data.
+
+
+
+ Recovered By
+
+
+
+
Recovery Success
+
+
+
+
+
+
+
Recovery Planned
+
+
+
+
+
+
+
Use Browser Position
+
+
+
+
+
+
+ Notes
+
+
+
+
+
+
+
+ Report Result
+ none
+
+
+
+
-
-
-
-
Statistics
+
Statistics
+
+
Recoveries
+
@@ -91,7 +168,7 @@
Radiosondes?
Found a Radiosonde?
- Click the 'car' icon on the top-right to submit a recovery notification.
+
Please click the 'balloon' icon on the top-right to submit a recovery notification!
Support Us!
If you use SondeHub regularly, please consider
supporting us on Patreon , or with a
donation on Paypal .
@@ -100,8 +177,8 @@
Support Us!
Contact Us!
For SondeHub usage questions and support, feel free to email us at
support@sondehub.org .
-
- You can also find us on IRC in
#habhub at
libera.chat .
+
+ You can also find us on
Discord and on IRC in
#habhub at
libera.chat .
Amateur HAB Launches?
You can find Amateur High-Altitude Balloon launches on the
Sondehub-Amateur Tracker .
@@ -122,9 +199,9 @@
Contribute
github/sondehub-tracker .
Bug reports, suggestions and pull requests are welcome. A huge thanks to RGP for developing the mobile tracker that this site is based on.
- Tracker Revision:
+ Tracker Revision:
{VER}
- Build Date:
+ Build Date:
{BUILD_DATE}
@@ -292,10 +369,10 @@ Chase Mode
Callsign
-
+
- Notice: If you enable this, your location will be uploaded to SondeHub; making it publicly visible on the map.
+ Notice: If you enable this, your location will be uploaded to SondeHub, making it publicly visible on the map for up to 12 hours.
@@ -323,43 +400,7 @@
Chase Mode
none
- Report Recovery
-
-
- You can report a recovery here. Enter the serial number (no type code, e.g. 'S1234567'), tick recovered/not recovered, and add some notes. If the sonde is not on the map, type its callsign into the top-left search box and press enter to retrieve historical data. You can then mark it as recovered. Optionally, you can use your location instead of the sonde's last location.
-
-
- Serial
-
-
-
-
Recovery Success
-
-
-
-
-
-
-
Use Car Position
-
-
-
-
-
-
- Notes
-
-
-
- Report Result
- none
-
-
-
-
-
+ Recovery reporting is now on the recoveries tab! (Balloon icon)
@@ -369,6 +410,9 @@ Report Recovery
Zoom in for realtime data!
+
+
Please report recovered sondes!
+
@@ -408,31 +452,13 @@ Report Recovery
-
+
+
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/js/app.js b/js/app.js
index a0df1bb..2731e23 100644
--- a/js/app.js
+++ b/js/app.js
@@ -40,6 +40,13 @@ function lhash_update(history_step) {
hash += "&nyan=1";
}
+ if(wvar.nena) {
+ hash += "&nena=1";
+ }
+ if(wvar.box) { // We just need something to change so we can trigger the back button correctly
+ hash += "&box="+wvar.box;
+ }
+
hash = encodeURI(hash);
// set state
if(history_supported) {
@@ -64,7 +71,9 @@ var wvar = {
zoom: true,
query: "",
nyan: false,
+ nena: false,
site: 0,
+ box: ""
};
@@ -87,6 +96,8 @@ function load_hash(no_refresh) {
focus: "",
query: "",
nyan: false,
+ nena: false,
+ box: ""
};
parms.forEach(function(v) {
@@ -96,23 +107,28 @@ function load_hash(no_refresh) {
switch(k) {
case "mt":
- if( baseMaps.hasOwnProperty(v) ) {
+ if( baseMaps.hasOwnProperty(v) && map) {
map.removeLayer(baseMaps[selectedLayer]);
selectedLayer = v;
map.addLayer(baseMaps[v]);
}
break;
case "mz":
- map.setZoom(parseInt(v));
+ if (map){
+ map.setZoom(parseInt(v));
+ }
break;
case "mc":
def.zoom = false;
manual_pan = true;
v = v.split(',');
var latlng = new L.LatLng(v[0], v[1]);
- map.panTo(latlng);
+ if (map){
+ map.panTo(latlng);
+ }
break;
case "f":
+ v = v.toUpperCase();
refocus = (follow_vehicle != v);
follow_vehicle = v;
def.focus = v;
@@ -122,40 +138,59 @@ function load_hash(no_refresh) {
if(modeList.indexOf(def.mode) == -1) def.mode = (is_mobile) ? modeDefaultMobile : modeDefault;
break;
case "q":
+ v = v.toUpperCase();
def.query = v;
$("header .search input[type='text']").val(v);
break;
case "nyan":
def[k] = !!parseInt(v);
break;
+ case "nena":
+ def[k] = !!parseInt(v);
+ break;
case "site":
focusID = v;
gotoSite(v);
break;
+ case "box":
+ def[k] = v;
+ break;
}
});
// check if we should force refresh
- ['mode','query','nyan'].forEach(function(k) {
+ ['mode','query','nyan','nena'].forEach(function(k) {
if(wvar[k] != def[k]) refresh = true;
});
+
+
$.extend(true, wvar, def);
+ if(map){
+ if (!def["box"]){
+ $(".flatpage").hide()
+ } else {
+ $(".flatpage").hide()
+ $("#"+def["box"]).show()
+ }
+ checkSize();
+ wvar["box"]= def["box"];
- // force refresh
- if(!no_refresh) {
- if(refresh) {
- zoomed_in = false;
- clean_refresh(wvar.mode, true);
- }
- else if(refocus) {
- $(".row.active").removeClass('active');
- $(".vehicle"+vehicles[wvar.focus].uuid).addClass('active');
- followVehicle(wvar.focus, manual_pan, true);
- }
- }
+ // force refresh
+ if(!no_refresh) {
+ if(refresh) {
+ zoomed_in = false;
+ clean_refresh(wvar.mode, true);
+ }
+ else if(refocus) {
+ $(".row.active").removeClass('active');
+ $(".vehicle"+vehicles[wvar.focus].uuid).addClass('active');
+ followVehicle(wvar.focus, manual_pan, true);
+ }
+ }
- lhash_update();
+ lhash_update();
+ }
}
window.onhashchange = load_hash;
@@ -180,6 +215,7 @@ for(var idx in params) {
$("header .search input[type='text']").val(wvar.query);
break;
case "nyan": wvar.nyan = true; break;
+ case "nena": wvar.nena = true; break;
case "focus": wvar.focus = decodeURIComponent(line[1]); break;
case "docid": wvar.docid = line[1]; break;
case "mode": wvar.mode = decodeURIComponent(line[1]); break;
@@ -188,24 +224,38 @@ for(var idx in params) {
// loads the tracker interface
function trackerInit() {
+ // update current position if we geolocation is available
+ if(currentPosition) updateCurrentPosition(currentPosition.lat, currentPosition.lon);
+
+
+
+ if (currentPosition && manual_pan == false){
+ coords = [currentPosition.lat, currentPosition.lon]
+ zoomLevel = 9;
+ map.setView(coords, zoomLevel, {animate: false});
+ }
$('#loading,#settingsbox,#aboutbox,#chasebox').hide(); // welcome screen
$('header,#main').show(); // interface elements
checkSize();
- if(map) return;
+ // if we there is enough screen space open aboutbox on startup
+ if(!is_mobile && !offline.get('opt_nowelcome') && $(window).width() > 900) $('.nav li.about').click();
+
if(is_mobile || wvar.enabled) $(".nav .wvar").hide();
if(!is_mobile) {
- $.getScript("js/init_plot.js", function() { checkSize(); if(!map) load(); });
+ $.getScript("js/_jquery.flot.js", function() {
+ $.getScript("js/plot_config.js", function() { checkSize(); if(!map) load(); });
+ });
if(wvar.graph) $('#telemetry_graph').attr('style','');
return;
}
- if(!map) load();
+ lhash_update(true);
}
-// if for some reason, applicationCache is not working, load the app after a 3s timeout
+// load the app after a 3s timeout
var initTimer = setTimeout(trackerInit, 3000);
var listScroll;
@@ -289,8 +339,7 @@ function positionUpdateError(error) {
switch(error.code)
{
case error.PERMISSION_DENIED:
- alert("no permission to use your location");
- $('#sw_chasecar').click(); // turn off chase car
+ $('#sw_chasecar').removeClass('on').addClass('off');
break;
default:
break;
@@ -305,89 +354,83 @@ var positionUpdateHandle = function(position) {
}
}
- //navigator.geolocation.getCurrentPosition(function(position) {
- var lat = position.coords.latitude;
- var lon = position.coords.longitude;
- var alt = (position.coords.altitude) ? position.coords.altitude : 0;
- var accuracy = (position.coords.accuracy) ? position.coords.accuracy : 0;
- var speed = (position.coords.speed) ? position.coords.speed : 0;
-
- // constantly update 'last updated' field, and display friendly time since last update
- if(!GPS_ts) {
- GPS_ts = parseInt(position.timestamp/1000);
-
- setInterval(function() {
- var delta_ts = parseInt(Date.now()/1000) - GPS_ts;
-
- // generate friendly timestamp
- var hours = Math.floor(delta_ts / 3600);
- var minutes = Math.floor(delta_ts / 60) % 60;
- var ts_str = (delta_ts >= 60) ?
- ((hours)?hours+'h ':'') +
- ((minutes)?minutes+'m':'') +
- ' ago'
- : 'just now';
- $('#cc_timestamp').text(ts_str);
- }, 30000);
-
- $('#cc_timestamp').text('just now');
- }
+ var lat = position.coords.latitude;
+ var lon = position.coords.longitude;
+ var alt = (position.coords.altitude) ? position.coords.altitude : 0;
+ var accuracy = (position.coords.accuracy) ? position.coords.accuracy : 0;
+ var speed = (position.coords.speed) ? position.coords.speed : 0;
+
+ // constantly update 'last updated' field, and display friendly time since last update
+ if(!GPS_ts) {
+ GPS_ts = parseInt(position.timestamp/1000);
+
+ setInterval(function() {
+ var delta_ts = parseInt(Date.now()/1000) - GPS_ts;
+
+ // generate friendly timestamp
+ var hours = Math.floor(delta_ts / 3600);
+ var minutes = Math.floor(delta_ts / 60) % 60;
+ var ts_str = (delta_ts >= 60) ?
+ ((hours)?hours+'h ':'') +
+ ((minutes)?minutes+'m':'') +
+ ' ago'
+ : 'just now';
+ $('#cc_timestamp').text(ts_str);
+ }, 30000);
+
+ $('#cc_timestamp').text('just now');
+ }
- // save position and update only if different is available
- if(CHASE_timer < (new Date()).getTime() &&
- (
- GPS_lat != lat ||
- GPS_lon != lon ||
- GPS_alt != alt ||
- GPS_speed != speed
- )
+ // save position and update only if different is available
+ if(CHASE_timer < (new Date()).getTime() &&
+ (
+ GPS_lat != lat ||
+ GPS_lon != lon ||
+ GPS_alt != alt ||
+ GPS_speed != speed
)
- {
- GPS_lat = lat;
- GPS_lon = lon;
- GPS_alt = alt;
- GPS_speed = speed;
- GPS_ts = parseInt(position.timestamp/1000);
- $('#cc_timestamp').text('just now');
-
- // update look angles once we get position
- if(follow_vehicle !== null && vehicles[follow_vehicle] !== undefined) {
- update_lookangles(follow_vehicle);
- }
+ )
+ {
+ GPS_lat = lat;
+ GPS_lon = lon;
+ GPS_alt = alt;
+ GPS_speed = speed;
+ GPS_ts = parseInt(position.timestamp/1000);
+ $('#cc_timestamp').text('just now');
+
+ // update look angles once we get position
+ if(follow_vehicle !== null && vehicles[follow_vehicle] !== undefined) {
+ update_lookangles(follow_vehicle);
+ }
- if(CHASE_enabled) {
- ChaseCar.updatePosition(callsign, position);
- CHASE_timer = (new Date()).getTime() + 15000;
- }
+ if(CHASE_enabled) {
+ ChaseCar.updatePosition(callsign, position);
+ CHASE_timer = (new Date()).getTime() + 15000;
}
- else { return; }
-
- // add/update marker on the map (tracker.js)
- updateCurrentPosition(lat, lon);
-
- // round the coordinates
- lat = parseInt(lat * 10000)/10000; // 4 decimal places (11m accuracy at equator)
- lon = parseInt(lon * 10000)/10000; // 4 decimal places
- speed = parseInt(speed * 10)/10; // 1 decimal place
- accuracy = parseInt(accuracy);
- alt = parseInt(alt);
-
- // dispaly them in the top right corner
- $('#app_name b').html(lat + ' ' + lon);
-
- // update chase car interface
- $('#cc_lat').text(lat);
- $('#cc_lon').text(lon);
- $('#cc_alt').text(alt + " m");
- $('#cc_accuracy').text(accuracy + " m");
- $('#cc_speed').text(speed + " m/s");
- /*
- },
- function() {
- // when there is no location
- $('#app_name b').html('mobile tracker');
- });
- */
+ }
+
+
+ // add/update marker on the map (sondehub.js)
+ updateCurrentPosition(lat, lon);
+
+ // round the coordinates
+ lat = parseInt(lat * 10000)/10000; // 4 decimal places (11m accuracy at equator)
+ lon = parseInt(lon * 10000)/10000; // 4 decimal places
+ speed = parseInt(speed * 10)/10; // 1 decimal place
+ accuracy = parseInt(accuracy);
+ alt = parseInt(alt);
+
+ // dispaly them in the top right corner
+ $('#app_name b').html(lat + ' ' + lon);
+
+ // update chase car interface
+ $('#cc_lat').text(lat);
+ $('#cc_lon').text(lon);
+ $('#cc_alt').text(alt + " m");
+ $('#cc_accuracy').text(accuracy + " m");
+ $('#cc_speed').text(speed + " m/s");
+
+
};
var twoZeroPad = function(n) {
@@ -435,6 +478,27 @@ var format_time_friendly = function(start, end) {
}
};
+var format_coordinates = function(lat, lon, name) {
+ var coords_text;
+ var ua = navigator.userAgent.toLowerCase();
+ var span = document.createElement('span')
+ var a = document.createElement("a")
+ span.appendChild(a)
+ // determine how to link the coordinates to a native app, if on a mobile device
+ if(ua.indexOf('iphone') > -1) {
+ a.href = 'maps://?q='+lat+','+lon
+ } else if(ua.indexOf('android') > -1) {
+ a.href = 'geo:'+lat+','+lon+'?q='+lat+','+lon+'('+name+')'
+ } else {
+ a.href = 'https://www.google.com/maps/search/?api=1&query='+lat+','+lon
+ a.target="_blank"
+ a.rel="noopener noreferrer"
+ }
+ a.innerText = roundNumber(lat, 5) + ', ' + roundNumber(lon, 5)
+
+ return span.innerHTML;
+};
+
// runs every second
var updateTime = function(date) {
// update timebox
@@ -456,18 +520,12 @@ var updateTime = function(date) {
}
};
-const version = "{VER}";
-
$(window).ready(function() {
// refresh timebox
setInterval(function() {
updateTime(new Date());
}, 1000);
- // Update Tracker version info
- $('#build_version').text(version);
- $('#build_date').text("{BUILD_DATE}");
-
// resize elements if needed
checkSize();
@@ -543,12 +601,6 @@ $(window).ready(function() {
$("#main").removeClass("drag");
});
- // confirm dialog when launchnig a native map app with coordinates
- //$('#main').on('click', '#launch_mapapp', function() {
- // var answer = confirm("Launch your maps app?");
- // return answer;
- //});
-
// follow vehicle by clicking on data
$('#main').on('click', '.row .data', function() {
var e = $(this).parent();
@@ -623,6 +675,14 @@ $(window).ready(function() {
default: pretty_name = name[0].toUpperCase() + name.slice(1);
}
}
+ var visible_box = $(".flatpage:visible");
+ if (visible_box.length > 0){
+ wvar.box = visible_box[0].id
+ } else {
+ wvar.box = null
+ }
+
+ lhash_update(true);
checkSize();
});
@@ -636,7 +696,6 @@ $(window).ready(function() {
field.removeAttr('disabled');
e.removeClass('on').addClass('off');
- if(navigator.geolocation) navigator.geolocation.clearWatch(CHASE_enabled);
CHASE_enabled = null;
//CHASE_enabled = false;
@@ -644,7 +703,7 @@ $(window).ready(function() {
if(currentPosition && currentPosition.marker) map.addLayer(currentPosition.marker);
// turning the switch on
} else {
- if(callsign.length == null || callsign.length < 3) { alert('Please enter a valid callsign, at least 3 characters'); return; }
+ if(callsign == null || callsign.length < 3) { alert('Please enter a valid callsign, at least 3 characters'); return; }
if(!callsign.match(/^[a-zA-Z0-9\_\-]+$/)) { alert('Invalid characters in callsign (use only a-z,0-9,-,_)'); return; }
field.attr('disabled','disabled');
@@ -664,8 +723,7 @@ $(window).ready(function() {
ChaseCar.updatePosition(callsign, { coords: { latitude: GPS_lat, longitude: GPS_lon, altitude: GPS_alt, speed: GPS_speed }});
}
- if(navigator.geolocation) CHASE_enabled = navigator.geolocation.watchPosition(positionUpdateHandle, positionUpdateError);
- //CHASE_enabled = true;
+ CHASE_enabled = true;
// hide the blue man
if(currentPosition && currentPosition.marker) map.removeLayer(currentPosition.marker);
@@ -683,6 +741,23 @@ $(window).ready(function() {
// turning the switch on
} else {
e.removeClass('off').addClass('on');
+ // Remove any planned recovery check.
+ $("#sw_recovery_planned").removeClass('on').addClass('off');
+ }
+ });
+ // Logic to switch the recovery Planned button
+ $("#sw_recovery_planned").click(function() {
+ var e = $(this);
+
+ // turning the switch off
+ if(e.hasClass('on')) {
+ e.removeClass('on').addClass('off');
+
+ // turning the switch on
+ } else {
+ e.removeClass('off').addClass('on');
+ // Set recovery OK to false.
+ $("#sw_recovery_ok").removeClass('on').addClass('off');
}
});
// Logic to switch the use car position button
@@ -703,11 +778,21 @@ $(window).ready(function() {
callsign = $(this).val().trim();
offline.set('callsign', callsign); // put in localStorage
CHASE_listenerSent = false;
+ $('#recovery_callsign').val(callsign);
+ });
+
+ $("#recovery_callsign").on('change keyup', function() {
+ callsign = $(this).val().trim();
+ offline.set('callsign', callsign); // put in localStorage
+ CHASE_listenerSent = false;
+ $('#cc_callsign').val(callsign);
});
+
// load value from localStorage
callsign = offline.get('callsign');
$('#cc_callsign').val(callsign);
+ $('#recovery_callsign').val(callsign);
// settings page
@@ -756,6 +841,18 @@ $(window).ready(function() {
else focusVehicle(null, true);
break;
case "opt_imperial":
+ if (map_scale){
+ map_scale.remove()
+ }
+ // we need to remove and add the zoom controls so they end up in the same position
+ zoom_controls.remove()
+ if (on) {
+ map_scale = L.control.scale({position:'bottomright', imperial:true, metric:false}).addTo(map);
+ } else {
+ map_scale = L.control.scale({position:'bottomright', imperial:false}).addTo(map);
+ }
+ zoom_controls.addTo(map);
+
case "opt_haxis_hours":
refreshUI();
break;
@@ -880,10 +977,7 @@ $(window).ready(function() {
});
navigator.geolocation.getCurrentPosition(positionUpdateHandle);
- // check for location update every 30sec
- //setInterval(positionUpdateHandle, 30000);
- // immediatelly check for position
- //positionUpdateHandle();
+ if(navigator.geolocation) navigator.geolocation.watchPosition(positionUpdateHandle, positionUpdateError);
}
// weather feature
@@ -982,7 +1076,8 @@ $(window).ready(function() {
$("header .search form").on('submit', function(e) {
e.preventDefault();
- var text = $("header .search input[type='text']").val();
+ var text = $("header .search input[type='text']").val().toUpperCase();
+ $("header .search input[type='text']")[0].value = text; // update field in case it wasn't already uppercase
if(text === wvar.query) return;
@@ -997,6 +1092,9 @@ $(window).ready(function() {
wvar.zoom = true;
}
+ // Insert the serial number into the recovery reporting serial number textbox
+ $("#pr_serial").val(text);
+
clean_refresh(wvar.mode, true, true);
});
});
@@ -1007,7 +1105,13 @@ function check_version(){
fetch(updateRequest)
.then(function(response){ return response.json()})
.then(function(response){
- if (response['version'] != version) {
+ if (response['version'] != document.body.dataset.version) {
+
+ caches.keys().then(function(names) { // wipe cache for fresh reload
+ for (let name of names)
+ caches.delete(name);
+ });
+
window.clearInterval(update_check)
reload_timer = window.setTimeout(update_site, response['refresh']*1000)
reload_end_time = new Date().getTime() +response['refresh']*1000
@@ -1022,6 +1126,19 @@ function update_site(){
window.location.reload(true)
}
+function check_banner(){
+ const bannerRequest = new Request("https://api.v2.sondehub.org/banner");
+ fetch(bannerRequest)
+ .then(function(response){ return response.json()})
+ .then(function(response){
+ if (response['banner']) {
+ document.getElementsByTagName("header")[0].style.backgroundColor = "#ff6259"
+ document.getElementsByTagName("header")[0].style.borderColor = "#eb3d34"
+ document.getElementById("banner").innerText = response['banner']
+ }
+ })
+}
+
function update_countdown(){
var date = new Date(0);
time_remaining = (reload_end_time - new Date().getTime())/1000
@@ -1031,4 +1148,8 @@ function update_countdown(){
}
check_version()
-update_check = setInterval(check_version, 15 * 60 * 1000)
\ No newline at end of file
+check_banner()
+update_check = setInterval(check_version, 15 * 60 * 1000)
+load_hash();
+startAjax();
+load();
\ No newline at end of file
diff --git a/js/chasecar.lib.js b/js/chasecar.lib.js
index bca130f..1c470e2 100644
--- a/js/chasecar.lib.js
+++ b/js/chasecar.lib.js
@@ -24,7 +24,7 @@ ChaseCar.updatePosition = function(callsign, position) {
var _doc = {
"software_name": "SondeHub Tracker",
- "software_version": "{VER}",
+ "software_version": document.body.dataset.version,
"uploader_callsign": callsign,
"uploader_position": [position.coords.latitude, position.coords.longitude, _position_alt],
"uploader_antenna": "Mobile Station",
@@ -45,9 +45,9 @@ ChaseCar.updatePosition = function(callsign, position) {
ChaseCar.markRecovered = function(){
- // Distance limits reinstated 2021-12-04
- _run_checks = true;
- _range_limit = 200000; // 200 km
+ // Remove range checks - 2025-01-24
+ _range_check = false;
+ _range_limit = 500000; // 200 km
// Get the serial number to be marked recovered
_serial = $("#pr_serial").val().trim();
@@ -55,15 +55,15 @@ ChaseCar.markRecovered = function(){
_notes = $("#pr_notes").val().trim();
// Check it exists.
- if(_serial.includes("chase") && _run_checks){
+ if(_serial.includes("chase")){
$('#pr_last_report').text("Invalid sonde callsign.");
return;
}
- _callsign = $("#cc_callsign").val().trim();
+ _callsign = $("#recovery_callsign").val().trim();
if (_callsign == "" || _callsign == undefined || _callsign.length == 0)
{
- $('#pr_last_report').text("Enter a callsign in the chase-car section above!");
+ $('#pr_last_report').text("Enter a callsign/name in the 'Recovered by' field!");
return;
}
@@ -109,8 +109,8 @@ ChaseCar.markRecovered = function(){
// Calculate the distance from the sonde
_lookangles = calculate_lookangles(_chaser, _sonde);
- if( (_lookangles.range > _range_limit ) && _run_checks){
- $('#pr_last_report').text("Outside distance limit.");
+ if( (_lookangles.range > _range_limit ) && _range_check){
+ $('#pr_last_report').text("Outside distance limit (500km).");
return;
}
@@ -120,28 +120,26 @@ ChaseCar.markRecovered = function(){
}
}
+ // Logic to make recovery & planned mutually exclusive is in app.js
+ _recovered = $("#sw_recovery_ok").hasClass('on');
+ _planned = $("#sw_recovery_planned").hasClass('on');
+
var _doc = {
"serial": _serial,
"lat": _recov_lat,
"lon": _recov_lon,
"alt": 0.0,
- "recovered": $("#sw_recovery_ok").hasClass('on'),
+ "recovered": _recovered,
+ "planned": _planned,
"recovered_by": _callsign,
"description": _notes
};
- // Yes this is not the right way to do this...
- // .. but it adds an extra bit of check.
- var res = grecaptcha.getResponse();
- if (res == "" || res == undefined || res.length == 0)
- {
- $('#pr_last_report').text("Do Recaptcha first!");
- return;
- }
$('#pr_last_report').text("Submitting report...");
+
$.ajax({
type: "PUT",
url: ChaseCar.recovery_uri,
diff --git a/js/format.js b/js/format.js
index a1ee090..9552181 100644
--- a/js/format.js
+++ b/js/format.js
@@ -49,6 +49,12 @@ function formatData(data, live) {
dataTempEntry.gps_alt = data[entry].alt;
dataTempEntry.gps_lat = data[entry].lat;
dataTempEntry.gps_lon = data[entry].lon;
+
+ // Discard positions with null values.
+ if (dataTempEntry.gps_lat == 0 && dataTempEntry.gps_lon == 0) {
+ continue;
+ }
+
if (data[entry].heading) {
dataTempEntry.gps_heading = data[entry].heading;
}
@@ -72,18 +78,26 @@ function formatData(data, live) {
if (data[entry].hasOwnProperty("humidity")) {
dataTempEntry.data.humidity = data[entry].humidity;
}
- if (data[entry].manufacturer) {
- dataTempEntry.data.manufacturer = data[entry].manufacturer;
- }
if (data[entry].hasOwnProperty("pressure")) {
dataTempEntry.data.pressure = data[entry].pressure;
}
if (data[entry].sats) {
dataTempEntry.data.sats = data[entry].sats;
+
+ // Drop frames where sats = 0! We do not want to be handling invalid positions.
+ if (dataTempEntry.data.sats == 0){
+ continue;
+ }
}
if (data[entry].hasOwnProperty("temp")) {
dataTempEntry.data.temperature_external = data[entry].temp;
}
+ // RS41 specific stuff
+ if (data[entry].hasOwnProperty("rs41_mainboard")) {
+ dataTempEntry.data.rs41_mainboard = data[entry].rs41_mainboard;
+ }
+ // Removed showing mainboard firmware, not really valuable
+
if (data[entry].type) {
dataTempEntry.data.type = data[entry].type;
dataTempEntry.type = data[entry].type;
@@ -92,6 +106,14 @@ function formatData(data, live) {
dataTempEntry.data.type = data[entry].subtype;
dataTempEntry.type = data[entry].subtype;
}
+
+ if (data[entry].manufacturer) {
+ // Instead of adding a separate manufacturer field, prefix the type with it.
+ if (dataTempEntry.data.type) {
+ dataTempEntry.data.type = data[entry].manufacturer + " " + dataTempEntry.data.type;
+ }
+ }
+
if (data[entry].xdata) {
dataTempEntry.data.xdata = data[entry].xdata;
@@ -137,6 +159,12 @@ function formatData(data, live) {
dataTempEntry.gps_alt = data[key][i].alt;
dataTempEntry.gps_lat = data[key][i].lat;
dataTempEntry.gps_lon = data[key][i].lon;
+
+ // Discard positions with null values.
+ if (dataTempEntry.gps_lat == 0 && dataTempEntry.gps_lon == 0) {
+ continue;
+ }
+
if (data[key][i].heading) {
dataTempEntry.gps_heading = data[key][i].heading;
}
@@ -160,14 +188,17 @@ function formatData(data, live) {
if (data[key][i].hasOwnProperty("humidity")) {
dataTempEntry.data.humidity = data[key][i].humidity;
}
- if (data[key][i].manufacturer) {
- dataTempEntry.data.manufacturer = data[key][i].manufacturer;
- }
+
if (data[key][i].hasOwnProperty("pressure")) {
dataTempEntry.data.pressure = data[key][i].pressure;
}
if (data[key][i].sats) {
dataTempEntry.data.sats = data[key][i].sats;
+
+ // Drop frames where sats = 0! We do not want to be handling invalid positions.
+ if (dataTempEntry.data.sats == 0){
+ continue;
+ }
}
if (data[key][i].hasOwnProperty("temp")) {
dataTempEntry.data.temperature_external = data[key][i].temp;
@@ -180,6 +211,21 @@ function formatData(data, live) {
dataTempEntry.data.type = data[key][i].subtype;
dataTempEntry.type = data[key][i].subtype;
}
+
+ if (data[key][i].manufacturer) {
+ // Instead of adding a separate manufacturer field, prefix the type with it.
+ if (dataTempEntry.data.type) {
+ dataTempEntry.data.type = data[key][i].manufacturer + " " + dataTempEntry.data.type;
+ }
+ }
+
+ // RS41 specific stuff
+ if (data[key][i].hasOwnProperty("rs41_mainboard")) {
+ dataTempEntry.data.rs41_mainboard = data[key][i].rs41_mainboard;
+ }
+ // Removed showing mainboard firmware, not really valuable
+
+ // XDATA Handling
if (data[key][i].xdata) {
dataTempEntry.data.xdata = data[key][i].xdata;
if (data[key][i].hasOwnProperty("pressure")) {
@@ -244,6 +290,12 @@ function formatData(data, live) {
dataTempEntry.gps_alt = data[i].alt;
dataTempEntry.gps_lat = data[i].lat;
dataTempEntry.gps_lon = data[i].lon;
+
+ // Discard positions with null values.
+ if (dataTempEntry.gps_lat == 0 && dataTempEntry.gps_lon == 0) {
+ continue;
+ }
+
if (data[i].heading) {
dataTempEntry.gps_heading = data[i].heading;
}
@@ -275,6 +327,11 @@ function formatData(data, live) {
}
if (data[i].sats) {
dataTempEntry.data.sats = data[i].sats;
+
+ // Drop frames where sats = 0! We do not want to be handling invalid positions.
+ if (dataTempEntry.data.sats == 0){
+ continue;
+ }
}
if (data[i].hasOwnProperty("temp")) {
dataTempEntry.data.temperature_external = data[i].temp;
@@ -285,7 +342,8 @@ function formatData(data, live) {
dataTempEntry.data.type = v1types[comment[0]];
dataTempEntry.type = v1types[comment[0]];
if (v1manufacturers.hasOwnProperty(dataTempEntry.type)) {
- dataTempEntry.data.manufacturer = v1manufacturers[dataTempEntry.type];
+ // dataTempEntry.data.manufacturer = v1manufacturers[dataTempEntry.type];
+ dataTempEntry.data.type = v1manufacturers[dataTempEntry.type] + " " + dataTempEntry.data.type;
}
}
dataTempEntry.data.frequency = comment[2];
@@ -297,6 +355,21 @@ function formatData(data, live) {
dataTempEntry.data.type = data[i].subtype;
dataTempEntry.type = data[i].subtype;
}
+
+ if (data[i].manufacturer) {
+ // Instead of adding a separate manufacturer field, prefix the type with it.
+ if (dataTempEntry.data.type) {
+ dataTempEntry.data.type = data[i].manufacturer + " " + dataTempEntry.data.type;
+ }
+ }
+
+ // RS41 specific stuff
+ if (data[i].hasOwnProperty("rs41_mainboard")) {
+ dataTempEntry.data.rs41_mainboard = data[i].rs41_mainboard;
+ }
+ // Removed showing mainboard firmware, not really valuable
+
+ // XDATA Handling
if (data[i].xdata) {
dataTempEntry.data.xdata = data[i].xdata;
if (data[i].hasOwnProperty("pressure")) {
diff --git a/js/plot_config.js b/js/plot_config.js
index f40315a..e66bc6d 100644
--- a/js/plot_config.js
+++ b/js/plot_config.js
@@ -77,9 +77,9 @@ function updateLegend(pos) {
if(outside && pij !== undefined) {
if(!polyMarker) {
- try {polyMarker = new L.Marker(vehicles[follow_vehicle].prediction_polyline.getLatLngs()[pij]).addTo(map);} catch (e) {};
+ try {polyMarker = new L.Marker(vehicles[follow_vehicle].prediction_polyline[0].getLatLngs()[pij]).addTo(map);} catch (e) {};
} else {
- try {polyMarker.setLatLng(vehicles[follow_vehicle].prediction_polyline.getLatLngs()[pij]);} catch (e) {};
+ try {polyMarker.setLatLng(vehicles[follow_vehicle].prediction_polyline[0].getLatLngs()[pij]);} catch (e) {};
}
}
diff --git a/js/tracker.js b/js/sondehub.js
similarity index 82%
rename from js/tracker.js
rename to js/sondehub.js
index b415025..1296cc4 100644
--- a/js/tracker.js
+++ b/js/sondehub.js
@@ -52,10 +52,10 @@ var focusID = 0;
var receiverCanvas = null;
-var sondePrefix = ["RS92", "RS92-SGP", "RS92-NGP", "RS41", "RS41-SG", "RS41-SGP", "RS41-SGM", "DFM", "DFM06", "DFM09", "DFM17", "M10", "M20", "iMet-1", "iMet-4", "iMet-54", "LMS6", "LMS6-400", "LMS6-1680", "iMS-100", "MRZ", "MTS01", "chase"];
+var sondePrefix = ["RS92", "RS92-SGP", "RS92-NGP", "RS41", "RS41-SG", "RS41-SGP", "RS41-SGM", "DFM", "DFM06", "DFM09", "DFM17", "M10", "M20", "PS20", "iMet-1", "iMet-4", "iMet-54", "LMS6", "LMS6-400", "LMS6-1680", "iMS-100", "MRZ", "MTS01", "WxR-301D", "chase"];
var sondeCodes = {
"07":"iMet-1", "11":"LMS6-403", "13":"RS92", "14":"RS92", "17":"DFM-09", "18":"DFM-06", "19":"MRZ-N1", "22":"RS-11G", "23":"RS41", "24":"RS41", "34":"iMet-4", "35":"iMS-100", "38":"WxR-301D", "41":"RS41", "42":"RS41", "52":"RS92-NGP",
- "54":"DFM-17", "62":"MRZ-3MK", "63":"M20", "65":"MTS01", "77":"M10", "82":"LMS6-1680", "84":"iMet-54"
+ "54":"DFM-17", "62":"MRZ-3MK", "63":"M20", "64":"PS20", "65":"MTS01", "77":"M10", "82":"LMS6-1680", "84":"iMet-54"
};
var unsupportedSondeCodes = {
"15":"PAZA-12M", "16":"PAZA-22", "20":"MK3", "21":"1524LA LORAN-C/GL5000", "26":"SRS-C34", "27":"AVK-MRZ", "28":"AVK–AK2-02", "29":"MARZ2-2", "30":"RS2-80", "33":"GTS1-2/GFE(L)", "45":"CF-06", "58":"AVK-BAR",
@@ -73,10 +73,8 @@ var manual_pan = false;
// due to complaints it was not visible enough. - 2023-06-03
var car_index = 0;
-var car_colors = ["blue", "red", "green", "yellow", "teal", "purple"];
-var balloon_index = 0;
-var balloon_colors_name = ["red", "blue", "green", "purple", "orange", "cyan"];
-var balloon_colors = ["#f00", "blue", "green", "#c700e6", "#ff8a0f", "#0fffca"];
+var car_colors = ["#a6cee3", "#1f78b4", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6"];
+var balloon_colors = ["#d95f02", "#7570b3", "#e7298a", "#e6ab02", "#a6761d", "#666666", "blue", "magenta", "#ffb300", "rebeccapurple"];
var nyan_color_index = 0;
var nyan_colors = ['nyan', 'nyan-coin', 'nyan-mon', 'nyan-pirate', 'nyan-cool', 'nyan-tothemax', 'nyan-pumpkin', 'nyan-afro', 'nyan-coin', 'nyan-mummy'];
@@ -170,7 +168,8 @@ var v1manufacturers = {
"LMS6-400": "Lockheed Martin",
"LMS6-1680": "Lockheed Martin",
"M10": "Meteomodem",
- "M20": "Meteomodem"
+ "M20": "Meteomodem",
+ "PS20": "Meteomodem"
}
var globalKeys = {
@@ -260,7 +259,12 @@ var globalKeys = {
"pcfh_controller_fw_date": "PCFH Controller Firmware Date",
"pcfh_fpga_fw_date": "PCFH FPGA Firmware Date",
"pcfh_temperature_pcb_date": "PCFH Temperature PCB Manufacture Date",
- "pcfh_main_pcb_date": "PCFH Main PCB Manufacture Date"
+ "pcfh_main_pcb_date": "PCFH Main PCB Manufacture Date",
+ "tacho_uptime": "KNMI Tachometer Uptime",
+ "tacho_delta": "KNMI Tachometer Delta",
+ "tacho_rpm": "KNMI Tachometer RPM",
+ "rs41_mainboard": "RS41 PCB Version",
+ "rs41_mainboard_fw": "RS41 PCB FW"
};
var globalSuffixes = {
@@ -319,6 +323,9 @@ var globalSuffixes = {
"pcfh_peltier_current_02": " A",
"pcfh_reserved_temperature": "°C",
"pcfh_thermocouple_reference_temperature": "°C",
+ "tacho_uptime": " S",
+ "tacho_delta": " s/400rev",
+ "tacho_rpm": " RPM"
};
// localStorage vars
@@ -563,7 +570,7 @@ function makeQuad(x, y, zoom) {
// map type list
-var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+var osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
});
@@ -583,12 +590,12 @@ var worldimagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/serv
});
worldimagery.id="WorldImagery";
-var stamen_terrain = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}{r}.png', {
- attribution: 'Map tiles by Stamen Design , CC BY 3.0 — Map data © OpenStreetMap contributors',
- subdomains: 'abcd',
- minZoom: 0,
- maxZoom: 18,
+var stamen_terrain = L.tileLayer('https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.png', {
+ minZoom: 0,
+ maxZoom: 20,
+ attribution: '© Stadia Maps , © OpenMapTiles © OpenStreetMap contributors',
});
+
stamen_terrain.id="Terrain";
var cartodb_voyager = L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
@@ -612,6 +619,16 @@ var getlost = L.tileLayer('https://live.getlost.com.au/{z}/{x}/{y}.jpg', {
});
getlost.id = "GetLost";
+var highSight = L.tileLayer('https://api.highsight.dev/v1/tiles/{z}/{x}/{y}?key=ARX3jYxzWotJVz7ZgdDiMQI18tZJ5WCk', {
+ attribution: '© HighSight ',
+ maxZoom: 9,
+ minZoom: 3,
+ crossOrigin: true
+ });
+
+highSight.id = "HighSight";
+
+
var baseMaps = {
"Mapnik": osm,
"DarkMatter": dark_matter,
@@ -619,62 +636,11 @@ var baseMaps = {
"Terrain": stamen_terrain,
"Voyager": cartodb_voyager,
"OpenTopoMap": opentopomap,
+ "HighSight": highSight
}
var selectedLayer = "Mapnik";
-// Tile load analytics - 2023-01-09
-// This code allows us to get some understanding of total tile loads across all users.
-var tile_loads = {
- "Mapnik": 0,
- "DarkMatter": 0,
- "WorldImagery": 0,
- "Terrain": 0,
- "Voyager": 0,
- "OpenTopoMap": 0,
-}
-
-// Add handlers to eadh tileload event to simply increment a counter.
-// We don't need any more data than this.
-osm.on('tileload', function() { tile_loads["Mapnik"]++ });
-dark_matter.on('tileload', function() { tile_loads["DarkMatter"]++ });
-worldimagery.on('tileload', function() { tile_loads["WorldImagery"]++ });
-stamen_terrain.on('tileload', function() { tile_loads["Terrain"]++ });
-cartodb_voyager.on('tileload', function() { tile_loads["Voyager"]++ });
-opentopomap.on('tileload', function() { tile_loads["OpenTopoMap"]++ });
-
-
-var last_sent_tile_loads = {}
-
-setInterval(function(){
-
- temp_tile_loads = Object.assign({},tile_loads);
-
- // Check if the tile load count has changed.
- // Using JSON stringify is a bit of a hack, but appropriate for this kind of job.
- if(JSON.stringify(last_sent_tile_loads) == JSON.stringify(temp_tile_loads)){
- // Tile loads havent changed, do nothing,
- } else {
- // Tile loads have changed. Update the store, and send the data.
- last_sent_tile_loads = Object.assign({},tile_loads);
-
- // Send!
-
- $.ajax({
- type: "PUT",
- url: "https://api.v2.sondehub.org/tiles/count",
- contentType: "application/json; charset=utf-8",
- dataType: "json",
- data: JSON.stringify({'client': clientID, 'tile_loads': last_sent_tile_loads}),
- });
- }
-
-}, 60000)
-
-
-
-
-
// set map if in memory
var maplayer = offline.get("map")
@@ -715,7 +681,7 @@ function throttle_events(event) {
function sub_to_nearby_sondes(){
let bounds = map.getBounds().pad(1); // expand by one viewport
- let zoomed_out = map.getZoom() <= 6;
+ let zoomed_out = map.getZoom() <= 8;
const sub_logging = false;
if (zoomed_out){
// If we are fairly zooomed out - only give the slow feed
@@ -736,12 +702,16 @@ function sub_to_nearby_sondes(){
// If zoomed in then we sub to specific sondes
for (let vehicle in vehicles){
let topic = "sondes/"+vehicle;
+ let prediction_topic = "prediction/"+vehicle;
+ let reverse_topic = "reverse-prediction/"+vehicle;
inside_bounds = bounds.contains(vehicles[vehicle].marker._latlng)
if (inside_bounds){
if (!clientTopic.includes(topic)){
if (sub_logging) console.log("Subbing to " + topic)
if (client.isConnected()) {
client.subscribe(topic);
+ client.subscribe(prediction_topic);
+ client.subscribe(reverse_topic);
}
clientTopic.push(topic)
}
@@ -752,7 +722,9 @@ function sub_to_nearby_sondes(){
} else {
if (sub_logging) console.log("unsubbing from " + topic)
if (client.isConnected()) {
- client.unsubscribe(topic)
+ client.unsubscribe(topic);
+ client.unsubscribe(prediction_topic);
+ client.unsubscribe(reverse_topic);
}
var topic_index = clientTopic.indexOf(topic)
if (topic_index > -1) {
@@ -790,6 +762,8 @@ function clean_refresh(text, force, history_step) {
if (wvar.query && sondePrefix.indexOf(wvar.query) == -1) {
var topic = "sondes/" + wvar.query;
client.subscribe(topic);
+ client.subscribe("prediction/"+wvar.query);
+ client.subscribe("reverse-prediction/"+wvar.query);
clientTopic = [topic];
} else {
client.subscribe("sondes-new/#");
@@ -802,7 +776,6 @@ function clean_refresh(text, force, history_step) {
wvar.mode = text;
document.getElementById("timeperiod").value = text;
- document.getElementById("timeperiod").disabled = true;
position_id = 0;
@@ -815,14 +788,13 @@ function clean_refresh(text, force, history_step) {
}
car_index = 0;
- balloon_index = 0;
nyan_color_index = 0;
stopFollow(force);
// add loading spinner in the vehicle list
$('#main .empty').parent().remove();
- $("#main .portrait,#main .landscape").append(
- '' + // right
'
' + // data
'';
- var c = 'Received via: ' +
+ var c = ' Received via' + num_callsigns + ': ' +
callsign_list + ' ';
if(!newPosition.callsign) c = '';
// mid for portrait
- var p = ''+formatDate(stringToDateUTC(newPosition.gps_time))+' datetime (local) ' +
+ var p = ''+formatDate(stringToDateUTC(newPosition.gps_time))+' datetime (viewer local) ' +
''+coords_text+' coordinates ' +
c +// receivers if any
'' +
@@ -1903,9 +2032,11 @@ function updateVehicleInfo(vcallsign, newPosition) {
// mid for landscape
var l = ((vehicle.vehicle_type == "car") ? '' : ''+ascent_text+' '+hrate_text+' rate v|h ') +
''+text_alt+' ('+text_alt_max+') altitude (max) ' +
- ''+formatDate(stringToDateUTC(newPosition.gps_time))+' datetime (local) ' +
+ ''+formatDate(stringToDateUTC(newPosition.gps_time))+' datetime (viewer local) ' +
''+coords_text+' coordinates ' +
- habitat_data(newPosition.data) +
+ // Enabling use of the larger data store
+ habitat_data(vehicle.data_fields, vehicle.data_fields_age, newPosition.gps_timestamp) +
+ //habitat_data(newPosition.data, vehicle.data_fields_age, newPosition.gps_timestamp) +
c + // receivers if any
'';
@@ -1937,6 +2068,7 @@ function skewTdelete () {
$('#deleteSkewt').hide();
$("#skewtSerial").text("Select a Radiosonde from the list and click 'SkewT' to plot. Note that not all radiosonde types are supported.");
box.hide();
+ lhash_update(true);
//$('.skewt').hide();
$("#skewt-plot").empty();
checkSize();
@@ -1966,6 +2098,7 @@ function skewTdraw (callsign) {
$('.flatpage, #homebox').hide();
$('.skewt').show();
box.show().scrollTop(0);
+ lhash_update(true);
checkSize();
};
@@ -2063,7 +2196,7 @@ function skewTdraw (callsign) {
// Extract temperature datapoint
if (entry.hasOwnProperty('temp')){
- if(parseFloat(entry.temp) > -270.0){
+ if(parseFloat(entry.temp) > -250.0){
_temp = parseFloat(entry.temp);
} else{
idx = idx + 1;
@@ -2076,15 +2209,15 @@ function skewTdraw (callsign) {
}
+ _dewp = null;
+
// Try and extract RH datapoint
if (entry.hasOwnProperty('humidity')){
if(parseFloat(entry.humidity) >= 0.0){
_rh = parseFloat(entry.humidity);
// Calculate the dewpoint
_dewp = (243.04 * (Math.log(_rh / 100) + ((17.625 * _temp) / (243.04 + _temp))) / (17.625 - Math.log(_rh / 100) - ((17.625 * _temp) / (243.04 + _temp))));
- } else {
- _dewp = -1000.0;
- }
+ }
}
// Calculate movement
@@ -2112,7 +2245,11 @@ function skewTdraw (callsign) {
break;
}
- _new_skewt_data = {"press": _pressure, "hght": _new_pos.alt, "temp": _temp, "dwpt": _dewp, "wdir": _wdir, "wspd": _wspd};
+ _new_skewt_data = {"press": _pressure, "hght": _new_pos.alt, "temp": _temp, "wdir": _wdir, "wspd": _wspd};
+
+ if (_dewp != null){
+ _new_skewt_data.dwpt = _dewp
+ }
skewt_data.push(_new_skewt_data);
@@ -2130,6 +2267,7 @@ function skewTdraw (callsign) {
$('.flatpage, #homebox').hide();
$('.skewt').show();
box.show().scrollTop(0);
+ lhash_update(true);
checkSize();
};
@@ -2164,16 +2302,20 @@ function set_polyline_visibility(vcallsign, val) {
if(vehicle.prediction_polyline) {
if (val) {
- map.addLayer(vehicle.prediction_polyline);
+ map.addLayer(vehicle.prediction_polyline[0]);
+ map.addLayer(vehicle.prediction_polyline[1]);
} else {
- map.removeLayer(vehicle.prediction_polyline);
+ map.removeLayer(vehicle.prediction_polyline[0]);
+ map.removeLayer(vehicle.prediction_polyline[1]);
}
}
if(vehicle.prediction_launch_polyline) {
if (val) {
- map.addLayer(vehicle.prediction_launch_polyline);
+ map.addLayer(vehicle.prediction_launch_polyline[0]);
+ map.addLayer(vehicle.prediction_launch_polyline[1]);
} else {
- map.removeLayer(vehicle.prediction_launch_polyline);
+ map.removeLayer(vehicle.prediction_launch_polyline[0]);
+ map.removeLayer(vehicle.prediction_launch_polyline[1]);
}
}
if(vehicle.prediction_target) {
@@ -2196,7 +2338,8 @@ function set_polyline_visibility(vcallsign, val) {
function removePrediction(vcallsign) {
if(vehicles[vcallsign].prediction_polyline) {
- map.removeLayer(vehicles[vcallsign].prediction_polyline);
+ map.removeLayer(vehicles[vcallsign].prediction_polyline[0]);
+ map.removeLayer(vehicles[vcallsign].prediction_polyline[1]);
vehicles[vcallsign].prediction_polyline = null;
}
if(vehicles[vcallsign].prediction_target) {
@@ -2225,19 +2368,48 @@ function drawLaunchPrediction(vcallsign) {
vehicle.prediction_launch_path = line;
- vehicle.prediction_launch_polyline = new L.Polyline(line, {
+ vehicle.prediction_launch_polyline = [new L.Polyline(line, {
color: balloon_colors[vehicle.color_index],
- opacity: 0.4,
+ opacity: 0.8,
weight: 3,
- })//.addTo(map);
-
- vehicle.prediction_launch_polyline.on('click', function (e) {
+ }),
+ new L.Polyline(line, {
+ color: "#000",
+ opacity: 0.1,
+ weight: 6,
+})
+]//.addTo(map);
+
+ vehicle.prediction_launch_polyline[0].on('click', function (e) {
+ mapInfoBox_handle_prediction_path(e);
+ });
+ vehicle.prediction_launch_polyline[1].on('click', function (e) {
mapInfoBox_handle_prediction_path(e);
});
- vehicle.prediction_launch_polyline.path_length = path_length;
+ vehicle.prediction_launch_polyline[0].path_length = path_length;
+ vehicle.prediction_launch_polyline[1].path_length = path_length;
}
+// Takes in an SVG for a balloon, parachute, target, car, etc and sets a dynamic-color
+// variable which that SVG can use to recolor any relevant elements.
+// See balloon.svg, target.svg, etc for examples
+var svg_cache = {}
+function recolorSVG(svg_path, color) {
+ if (svg_cache[svg_path] == undefined){
+ const xhr = new XMLHttpRequest();
+ xhr.open('GET', svg_path, false);
+ xhr.send();
+
+ const parser = new DOMParser();
+ const svgDocument = parser.parseFromString(xhr.responseText, 'image/svg+xml');
+ svg_cache[svg_path] = svgDocument;
+ }
+ const svgDoc = svg_cache[svg_path]
+ svgDoc.documentElement.style.setProperty("--dynamic-color", color);
+ return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgDoc.documentElement.outerHTML);
+ }
+
function redrawPrediction(vcallsign) {
var vehicle = vehicles[vcallsign];
var data = vehicle.prediction.data;
@@ -2277,19 +2449,31 @@ function redrawPrediction(vcallsign) {
vehicle.prediction_path = line;
if(vehicle.prediction_polyline !== null) {
- vehicle.prediction_polyline.setLatLngs(line);
+ vehicle.prediction_polyline[0].setLatLngs(line);
+ vehicle.prediction_polyline[1].setLatLngs(line);
} else {
- vehicle.prediction_polyline = new L.Polyline(line, {
+ vehicle.prediction_polyline = [new L.Polyline(line, {
color: balloon_colors[vehicle.color_index],
- opacity: 0.5, // Was 0.4
+ opacity: 0.8, // Was 0.4
weight: 3,
- })//.addTo(map);
- vehicle.prediction_polyline.on('click', function (e) {
+ }),
+ new L.Polyline(line, {
+ color: "#000",
+ opacity: 0.1, // Was 0.4
+ weight: 6,
+ })
+
+ ]//.addTo(map);
+ vehicle.prediction_polyline[0].on('click', function (e) {
mapInfoBox_handle_prediction_path(e);
});
+ vehicle.prediction_polyline[1].on('click', function (e) {
+ mapInfoBox_handle_prediction_path(e);
+ })
}
- vehicle.prediction_polyline.path_length = path_length;
+ vehicle.prediction_polyline[0].path_length = path_length;
+ vehicle.prediction_polyline[1].path_length = path_length;
var image_src;
@@ -2297,7 +2481,7 @@ function redrawPrediction(vcallsign) {
if(vehicle.prediction_target) {
vehicle.prediction_target.setLatLng(latlng);
} else {
- image_src = host_url + markers_url + "target-" + balloon_colors_name[vehicle.color_index] + ".png";
+ image_src = recolorSVG(host_url + markers_url + "target.svg", balloon_colors[vehicle.color_index]);
predictionIcon = new L.icon({
iconUrl: image_src,
iconSize: [20,20],
@@ -2317,13 +2501,26 @@ function redrawPrediction(vcallsign) {
vehicle.prediction_target.pred_type = "Prediction Type: Float\n";
} else {
if(vehicle.prediction.descending == 1){
- vehicle.prediction_target.pred_type = "Prediction Type: Standard \n" +
- "Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+ vehicle.prediction_target.pred_type = "Prediction Type: Standard \n"
+ if (offline.get('opt_imperial')){
+ vehicle.prediction_target.pred_type = vehicle.prediction_target.pred_type + "Descent Rate: " + (vehicle.prediction.descent_rate * 3.2808399).toFixed(1) + " ft/s \n";
+ } else {
+ vehicle.prediction_target.pred_type = vehicle.prediction_target.pred_type + "Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+ }
+
} else {
- vehicle.prediction_target.pred_type = "Prediction Type: Standard \n" +
- "Ascent Rate: " + vehicle.prediction.ascent_rate.toFixed(1) + " m/s \n" +
- "Burst Altitude: " + vehicle.prediction.burst_altitude.toFixed(0) + " m\n" +
- "Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+ if (offline.get('opt_imperial')){
+ vehicle.prediction_target.pred_type = "Prediction Type: Standard \n" +
+ "Ascent Rate: " + (vehicle.prediction.ascent_rate * 3.2808399).toFixed(1) + " ft/s \n" +
+ "Burst Altitude: " + (vehicle.prediction.burst_altitude * 3.2808399).toFixed(0) + " ft\n" +
+ "Descent Rate: " + (vehicle.prediction.descent_rate * 3.2808399).toFixed(1) + " ft/s \n";
+
+ } else {
+ vehicle.prediction_target.pred_type = "Prediction Type: Standard \n" +
+ "Ascent Rate: " + vehicle.prediction.ascent_rate.toFixed(1) + " m/s \n" +
+ "Burst Altitude: " + vehicle.prediction.burst_altitude.toFixed(0) + " m\n" +
+ "Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+ }
}
}
@@ -2341,7 +2538,8 @@ function redrawPrediction(vcallsign) {
vehicle.prediction_burst = new L.Marker(latlng_burst, {
zIndexOffset: Z_SHADOW,
icon: burstIcon,
- }).addTo(map);
+ });
+ vehicle.prediction_burst.pred_type = "Burst \n";
vehicle.prediction_burst.on('click', function (e) {
mapInfoBox_handle_prediction(e);
});
@@ -2351,13 +2549,25 @@ function redrawPrediction(vcallsign) {
vehicle.prediction_burst.pred_type = "Prediction Type: Float\n";
} else {
if(vehicle.prediction.descending == 1){
- vehicle.prediction_burst.pred_type = "Prediction Type: Standard \n" +
- "Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+ vehicle.prediction_burst.pred_type = "Prediction Type: Standard \n"
+ if (offline.get('opt_imperial')){
+ vehicle.prediction_burst.pred_type = vehicle.prediction_burst.pred_type + "Descent Rate: " + (vehicle.prediction.descent_rate * 3.2808399).toFixed(1) + " ft/s \n";
+ } else {
+ vehicle.prediction_burst.pred_type = vehicle.prediction_burst.pred_type + "Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+ }
} else {
- vehicle.prediction_burst.pred_type = "Prediction Type: Standard \n" +
+ if (offline.get('opt_imperial')){
+ vehicle.prediction_burst.pred_type = "Prediction Type: Standard \n" +
+ "Ascent Rate: " + (vehicle.prediction.ascent_rate * 3.2808399).toFixed(1) + " ft/s \n" +
+ "Burst Altitude: " + (vehicle.prediction.burst_altitude * 3.2808399).toFixed(0) + " ft\n" +
+ "Descent Rate: " + (vehicle.prediction.descent_rate * 3.2808399).toFixed(1) + " ft/s \n";
+ } else {
+ vehicle.prediction_burst.pred_type = "Prediction Type: Standard \n" +
"Ascent Rate: " + vehicle.prediction.ascent_rate.toFixed(1) + " m/s \n" +
"Burst Altitude: " + vehicle.prediction.burst_altitude.toFixed(0) + " m\n" +
"Descent Rate: " + vehicle.prediction.descent_rate.toFixed(1) + " m/s \n";
+
+ }
}
}
} else {
@@ -2586,51 +2796,68 @@ function mapInfoBox_handle_path_old(vehicle, id) {
div = document.createElement('div');
html = "";
- html += "
"+data.serial+" ("+data.datetime+")
";
+ html += "
";
html += "
";
- html += "
"+roundNumber(data.lat, 5) + ', ' + roundNumber(data.lon, 5)+"
";
+ html += "
";
var imp = offline.get('opt_imperial');
var text_alt = Number((imp) ? Math.floor(3.2808399 * parseInt(data.alt)) : parseInt(data.alt)).toLocaleString("us");
- text_alt += " " + ((imp) ? 'ft':'m');
+ text_alt += " " + ((imp) ? 'ft':'m');
- html += "
Altitude: "+text_alt+"
";
- html += "
Time: "+formatDate(stringToDateUTC(data.datetime))+"
";
+ html += "
Altitude:
";
+ html += "
Time:
";
var value = vehicle.path_length;
- html += "
Distance: ";
+ html += "
Distance: ";
if(offline.get('opt_imperial')) {
- html += Math.round(value*0.000621371192) + " mi";
+ var distance = Math.round(value*0.000621371192) + " mi";
} else {
- html += Math.round(value/10)/100 + " km";
+ var distance = Math.round(value/10)/100 + " km";
}
html += "
";
- html += "
Duration: " + format_time_friendly(vehicle.start_time, convert_time(vehicle.curr_position.gps_time)) + "
";
+ html += "
Duration:
";
html += "
";
if (data.hasOwnProperty("humidity")) {
- html += "
Relative Humidity: " + data.humidity + " %
";
+ html += "
Relative Humidity: %
";
};
if (data.hasOwnProperty("temp")) {
- html += "
Temperature External: " + data.temp + "°C
";
+ html += "
Temperature External: °C
";
};
if (data.hasOwnProperty("comment")) {
- html += "
Comment: " + data.comment + "
";
+ html += "
Comment:
";
};
html += "
";
html += "
"
if (data.hasOwnProperty("uploader_callsign")) {
- html += "
" + data.uploader_callsign + "
";
+ html += "
";
};
+
+
div.innerHTML = html;
+ div.getElementsByClassName("old_path_serial")[0].textContent = data.serial
+ div.getElementsByClassName("old_path_time")[0].textContent = "("+data.datetime+")"
+ div.getElementsByClassName("old_path_coords")[0].innerHTML = format_coordinates(data.lat, data.lon, data.serial)
+ div.getElementsByClassName("old_path_alt")[0].textContent = text_alt
+ div.getElementsByClassName("old_path_time_short")[0].textContent = formatDate(stringToDateUTC(data.datetime))
+ div.getElementsByClassName("old_path_time_distance")[0].textContent = distance
+ div.getElementsByClassName("old_path_duration")[0].textContent = format_time_friendly(vehicle.start_time, convert_time(vehicle.curr_position.gps_time))
+ div.getElementsByClassName("old_path_humidity")[0].textContent = data.humidity
+ div.getElementsByClassName("old_path_temp")[0].textContent = data.temp
+ div.getElementsByClassName("old_path_comment")[0].textContent = data.comment
+
+ if (data.hasOwnProperty("uploader_callsign")) {
+ div.getElementsByClassName("old_path_uploader_callsign")[0].textContent = data.uploader_callsign
+ }
+
mapInfoBox.setContent(div);
mapInfoBox.openOn(map);
@@ -2661,87 +2888,90 @@ function mapInfoBox_handle_path_new(data, vehicle, date) {
div = document.createElement('div');
html = "
";
- html += "
"+data.serial+" ("+date+")
";
+ html += "
";
html += "
";
- html += "
"+roundNumber(data.lat, 5) + ', ' + roundNumber(data.lon, 5)+"
";
+ html += "
";
var imp = offline.get('opt_imperial');
var text_alt = Number((imp) ? Math.floor(3.2808399 * parseInt(data.alt)) : parseInt(data.alt)).toLocaleString("us");
- text_alt += " " + ((imp) ? 'ft':'m');
+ text_alt += " " + ((imp) ? 'ft':'m');
- html += "
Altitude: "+text_alt+"
";
- html += "
Time: "+formatDate(stringToDateUTC(date))+"
";
+ html += "
Altitude:
";
+ html += "
Time:
";
var value = vehicle.path_length;
- html += "
Distance: ";
+ html += "
Distance: ";
if(offline.get('opt_imperial')) {
- html += Math.round(value*0.000621371192) + " mi";
+ var distance = Math.round(value*0.000621371192) + " mi";
} else {
- html += Math.round(value/10)/100 + " km";
+ var distance = Math.round(value/10)/100 + " km";
}
- html += "
";
- html += "
Duration: " + format_time_friendly(vehicle.start_time, convert_time(vehicle.curr_position.gps_time)) + "
";
+ html += "
";
+ html += "
Duration:
";
- html += "
";
+ html += "
";
- if (data.hasOwnProperty("batt")) {
- html += "
Battery Voltage: " + data.batt + " V
";
- };
- if (data.hasOwnProperty("tx_frequency")) {
- html += "
TX Frequency: " + data.tx_frequency + " MHz
";
- } else if (data.hasOwnProperty("frequency")) {
- html += "
Frequency: " + data.frequency + " MHz
";
- };
- if (data.hasOwnProperty("humidity")) {
- html += "
Relative Humidity: " + data.humidity + " %
";
- };
- if (data.hasOwnProperty("manufacturer")) {
- html += "
Manufacturer: " + data.manufacturer + "
";
- };
- if (data.hasOwnProperty("pressure")) {
- html += "
Pressure: " + data.pressure + " Pa
";
- };
- if (data.hasOwnProperty("sats")) {
- html += "
Satellites: " + data.sats + "
";
- };
- if (data.hasOwnProperty("temp")) {
- html += "
Temperature External: " + data.temp + "°C
";
- };
- if (data.hasOwnProperty("subtype")) {
- html += "
Sonde Type: " + data.subtype + "
";
- } else if (data.hasOwnProperty("type")) {
- html += "
Sonde Type: " + data.type + "
";
- };
+ function prop(parent, field_name, description, unit="", fixed=undefined){
+ if (data.hasOwnProperty(field_name)){
+ var div = document.createElement("div")
+ var b = document.createElement("b")
+ b.innerText = description + ": "
+ var span = document.createElement("span")
+ var value = data[field_name];
+ if (fixed){
+ value = value.toFixed(fixed)
+ }
+ span.textContent = value + " " + unit
+ div.appendChild(b)
+ div.appendChild(span)
+ parent.appendChild(div)
+ return true
+ }
+ return false
+ }
+ var xdata_fields = document.createElement("div");
if (data.hasOwnProperty("xdata")) {
html += "
";
html += "
"
- html += "
XDATA: " + data.xdata + "
";
+ html += "
";
if (data.hasOwnProperty("pressure")) {
xdata_pressure = data.pressure;
} else {
xdata_pressure = 1100.0;
}
var tempXDATA = parseXDATA(data.xdata, xdata_pressure);
+
for (let field in tempXDATA) {
if (tempXDATA.hasOwnProperty(field)) {
+ var xdiv = document.createElement("div");
+ var xb = document.createElement("b");
+ var xs = document.createElement("span");
+ xdiv.appendChild(xb)
+ xdiv.appendChild(xs)
+ xdata_fields.appendChild(xdiv)
if (field == "xdata_instrument") {
- html += "
XDATA Instrument: " + tempXDATA.xdata_instrument.join(', ') + "
";
+ xb.textContent = "XDATA Instrument: "
+ xs.textContent = tempXDATA.xdata_instrument.join(', ')
} else {
if (globalKeys.hasOwnProperty(field)) {
if (globalSuffixes.hasOwnProperty(field)) {
- html += "
" + globalKeys[field] + ": " + tempXDATA[field] + globalSuffixes[field] + "
";
+ xb.textContent = globalKeys[field] + ": "
+ xs.textContent = tempXDATA[field] + globalSuffixes[field]
} else {
- html += "
" + globalKeys[field] + ": " + tempXDATA[field] + "
";
+ xb.textContent = globalKeys[field] + ": "
+ xs.textContent = tempXDATA[field]
}
} else {
if (globalSuffixes.hasOwnProperty(field)) {
- html += "
" + guess_name(field) + ": " + tempXDATA[field] + globalSuffixes[field] + "
";
+ xb.textContent = guess_name(field) + ": "
+ xs.textContent = tempXDATA[field] + globalSuffixes[field]
} else {
- html += "
" + guess_name(field) + ": " + tempXDATA[field] + "
";
+ xb.textContent = guess_name(field) + ": "
+ xs.textContent = tempXDATA[field]
}
}
}
@@ -2772,11 +3002,48 @@ function mapInfoBox_handle_path_new(data, vehicle, date) {
callsign_list.push(_new_call); // catch cases where there are no fields
}
- callsign_list = callsign_list.join("
");
-
- html += callsign_list + "
";
+ callsign_list = callsign_list.join("\n");
+ callsign_span = document.createElement("span")
+ callsign_span.innerText = callsign_list
div.innerHTML = html;
+ div.appendChild(callsign_span)
+
+ div.getElementsByClassName("new_path_serial")[0].textContent = data.serial
+ div.getElementsByClassName("new_path_time")[0].textContent = "("+date+")"
+
+ div.getElementsByClassName("new_path_coords")[0].innerHTML = format_coordinates(data.lat, data.lon, data.serial); // for compat we are generating safeish url in format_coordinates
+
+ div.getElementsByClassName("new_path_alt")[0].textContent = text_alt
+ div.getElementsByClassName("new_path_time_short")[0].textContent = formatDate(stringToDateUTC(date))
+
+
+ div.getElementsByClassName("new_path_time_distance")[0].textContent = distance
+
+ div.getElementsByClassName("new_path_duration")[0].textContent = format_time_friendly(vehicle.start_time, convert_time(vehicle.curr_position.gps_time))
+
+
+ var prop_parent = div.getElementsByClassName("new_path_props")[0]
+ prop(prop_parent,"batt", "Battery Voltage", "V");
+
+ if (!prop(prop_parent,"tx_frequency", "TX Frequency", "MHz", 3)){
+ prop(prop_parent,"frequency", "Frequency", "MHz", 3);
+ }
+
+
+ prop(prop_parent,"humidity", "Relative Humidity","%", 1);
+ prop(prop_parent,"manufacturer", "Manufacturer");
+ prop(prop_parent,"pressure", "Pressure", "Pa", 1);
+ prop(prop_parent,"sats", "Satellites");
+ prop(prop_parent,"temp", "Temperature External", "°C", 1);
+
+ if (!prop(prop_parent,"subtype", "Sonde Type")){
+ prop(prop_parent,"type", "Sonde Type")
+ }
+ prop(prop_parent,"xdata", "XDATA");
+ if (data.hasOwnProperty("xdata")) {
+ div.getElementsByClassName("new_path_xdata_prop")[0].appendChild(xdata_fields)
+ }
mapInfoBox.setContent(div);
mapInfoBox.openOn(map);
@@ -2797,20 +3064,7 @@ function mapInfoBox_handle_prediction(event) {
altitude = Math.round(data.alt) + " m";
}
- var coords_text;
- var ua = navigator.userAgent.toLowerCase();
-
- // determine how to link the vehicle coordinates to a native app, if on a mobile device
- if(ua.indexOf('iphone') > -1) {
- coords_text = '
' +
- roundNumber(data.lat, 5) + ', ' + roundNumber(data.lon, 5) + ' ';
- } else if(ua.indexOf('android') > -1) {
- coords_text = '
' +
- roundNumber(data.lat, 5) + ', ' + roundNumber(data.lon, 5) +' ';
- } else {
- coords_text = '
' +
- roundNumber(data.lat, 5) + ', ' + roundNumber(data.lon, 5) +' ';
- }
+ var coords_text = format_coordinates(data.lat, data.lon, "Prediction");
mapInfoBox.setContent("
" +
formatDate(new Date(parseInt(data.time) * 1000), true) + "\n\n" +
@@ -2891,10 +3145,10 @@ var marker_rotate_setup = function(marker, image_src) {
else {
marker.iconImg = new Image();
icon_cache[image_src] = marker.iconImg;
- marker.iconImg.onload = function() {
+ marker.iconImg.addEventListener("load", function() {
if(!marker.rotated) marker.setCourse(90);
marker.setLatLng(marker.getLatLng());
- };
+ })
marker.iconImg.src = image_src;
}
};
@@ -2925,9 +3179,12 @@ function addPosition(position) {
var horizon_circle_title = null;
var subhorizon_circle_title = null;
if(vcallsign.search(/(chase)/i) != -1) {
+ if (offline.get("opt_hide_chase") ){
+ return
+ }
vehicle_type = "car";
color_index = car_index++ % car_colors.length;
- image_src = host_url + markers_url + "car-" + car_colors[color_index] + ".png";
+ image_src = recolorSVG(host_url + markers_url + "car.svg", car_colors[color_index]);
image_src_size = [55,25];
image_src_offset = [0,-25];
@@ -2968,32 +3225,19 @@ function addPosition(position) {
weight: 3,
})
];
- }
- else if(vcallsign == "XX") {
- vehicle_type = "xmark";
- image_src = host_url + markers_url + "balloon-xmark.png";
- image_src_size = [48,38];
- image_src_offset = [0,-38];
-
- xmarkIcon = new L.icon({
- iconUrl: image_src,
- iconSize: image_src_size,
- iconAnchor: [24, 18],
- });
-
- marker = new L.Marker(point, {
- icon: xmarkIcon,
- title: vcallsign,
- zIndexOffset: Z_CAR,
- });
-
- marker.addTo(map);
} else {
vehicle_type = "balloon";
- color_index = balloon_index++ % balloon_colors.length;
+ let colorHash = 0;
+ for (let i = 0; i < vcallsign.length; i++){
+ colorHash += vcallsign.charCodeAt(i);
+ }
+ color_index = colorHash % balloon_colors.length;
- image_src = host_url + markers_url + "balloon-" +
- ((vcallsign == "PIE") ? "rpi" : balloon_colors_name[color_index]) + ".png";
+ if(wvar.nena){
+ // All the balloon are red.
+ color_index = 0;
+ }
+ image_src = recolorSVG(host_url + markers_url + "balloon.svg", balloon_colors[color_index]);
image_src_size = [46,84];
image_src_offset = [-35,-46];
@@ -3038,7 +3282,7 @@ function addPosition(position) {
};
marker.shadow = marker_shadow;
- marker.balloonColor = (vcallsign == "PIE") ? "rpi" : balloon_colors_name[color_index];
+ marker.balloonColor = balloon_colors[color_index];
marker.mode = 'balloon';
marker.setMode = function(mode) {
if(this.mode == mode) return;
@@ -3051,9 +3295,9 @@ function addPosition(position) {
map.removeLayer(vehicle.subhorizon_circle);
map.removeLayer(vehicle.horizon_circle_title);
map.removeLayer(vehicle.subhorizon_circle_title);
-
+ img_src = recolorSVG(host_url + markers_url + "payload.svg", this.balloonColor);
img = new L.icon ({
- iconUrl: host_url + markers_url + "payload-" + this.balloonColor + ".png",
+ iconUrl: img_src,
iconSize: [17,18],
iconAnchor: [8,14],
tooltipAnchor: [0,-20],
@@ -3069,15 +3313,17 @@ function addPosition(position) {
}
if(mode == "parachute") {
+ img_src = recolorSVG(host_url + markers_url + "parachute.svg", this.balloonColor);
img = new L.icon ({
- iconUrl: host_url + markers_url + "parachute-" + this.balloonColor + ".png",
+ iconUrl: img_src,
iconSize: [46,84],
tooltipAnchor: [0,-98],
iconAnchor: [23,90],
});
} else {
+ img_src = recolorSVG(host_url + markers_url + "balloon.svg", this.balloonColor);
img = new L.icon ({
- iconUrl: host_url + markers_url + "balloon-" + this.balloonColor + ".png",
+ iconUrl: img_src,
iconSize: [46,84],
tooltipAnchor: [0,-98],
iconAnchor: [23,90],
@@ -3132,7 +3378,8 @@ function addPosition(position) {
horizon_circle_title = new L.Marker(point, {
icon: horizon_circle_title_icon,
- interactive: false,
+ interactive: true,
+ title: "Line-of-right (radio) horizon of the payload"
});
if (offline.get("opt_hide_horizon")) {
@@ -3164,7 +3411,8 @@ function addPosition(position) {
subhorizon_circle_title = new L.Marker(point, {
icon: subhorizon_circle_title_icon,
- interactive: false,
+ interactive: true,
+ title: "Payload is greater than 5 degrees above the horizon within this circle, which indicates it should be fairly easily receivable."
});
if (offline.get("opt_hide_horizon")) {
@@ -3185,20 +3433,26 @@ function addPosition(position) {
color: balloon_colors[color_index],
opacity: 1,
weight: 3,
+ }),
+ new L.Polyline(point, {
+ color: "#fff",
+ opacity: 0.6,
+ weight: 6,
})
];
}
if (!offline.get("opt_hide_titles")) {
if (vehicle_type == "car") {
- title = marker.bindTooltip(vcallsign, {direction: 'center', permanent: 'true', className: 'serialtooltip'});
+ title = marker.bindTooltip(vcallsign, {direction: 'center', permanent: 'false', className: 'serialtooltip'});
} else {
- title = marker.bindTooltip((tempTitle), {direction: 'center', permanent: 'true', className: 'serialtooltip'});
+ title = marker.bindTooltip((tempTitle), {direction: 'center', permanent: 'false', className: 'serialtooltip'});
}
} else {
title = null;
}
+
var vehicle_info = {
callsign: vcallsign,
uuid: elm_uuid++,
@@ -3221,6 +3475,8 @@ function addPosition(position) {
positions_alts: [],
path_length: 0,
curr_position: position,
+ data_fields: {},
+ data_fields_age: {},
line: [],
polyline_visible: polyline_visible,
polyline: polyline !== null ? polyline : [
@@ -3293,11 +3549,13 @@ function addPosition(position) {
vehicle_info.kill = function() {
$(".vehicle"+vehicle_info.uuid).remove();
potentialobjects = [marker, marker_shadow, landing_marker, horizon_circle, horizon_circle_title, subhorizon_circle, subhorizon_circle_title, polyline];
- if (map.hasLayer(vehicle_info["prediction_polyline"])) {
- map.removeLayer(vehicle_info["prediction_polyline"]);
+ if (vehicle_info["prediction_polyline"] && map.hasLayer(vehicle_info["prediction_polyline"][0])) {
+ map.removeLayer(vehicle_info["prediction_polyline"][0]);
+ map.removeLayer(vehicle_info["prediction_polyline"][1]);
}
- if (map.hasLayer(vehicle_info["prediction_launch_polyline"])) {
- map.removeLayer(vehicle_info["prediction_launch_polyline"]);
+ if (vehicle_info["prediction_launch_polyline"] && map.hasLayer(vehicle_info["prediction_launch_polyline"][0])) {
+ map.removeLayer(vehicle_info["prediction_launch_polyline"][0]);
+ map.removeLayer(vehicle_info["prediction_launch_polyline"][1]);
}
if (map.hasLayer(vehicle_info["prediction_target"])) {
map.removeLayer(vehicle_info["prediction_target"]);
@@ -3333,6 +3591,7 @@ function addPosition(position) {
var new_latlng = new L.LatLng(position.gps_lat, position.gps_lon);
var new_ts = convert_time(position.gps_time);
+ position.gps_timestamp = new_ts;
var curr_ts = convert_time(vehicle.curr_position.gps_time);
var new_alt = position.gps_alt;
var dt = (new_ts - curr_ts) / 1000; // convert to seconds
@@ -3421,7 +3680,7 @@ function addPosition(position) {
};
// if car doesn't report heading, we calculate it from the last position
- if(vehicle.num_positions > 1 && vehicle.vehicle_type == 'car' && 'gps_heading' in position && position.gps_heading === "") {
+ if(vehicle.num_positions > 1 && vehicle.vehicle_type == 'car') {
// Source
var startLat = toRadians(vehicle.curr_position.gps_lat);
@@ -3776,24 +4035,26 @@ function refresh() {
data: data_str,
dataType: "json",
success: function(data, textStatus) {
- if (wvar.query != null && JSON.stringify(data).indexOf(wvar.query) == -1) {
- refreshSingle(wvar.query);
- } else {
- response = formatData(data, false);
- update(response, true);
- $("#stTimer").attr("data-timestamp", response.fetch_timestamp);
+ var checkLoadedTimer = setInterval(() => {
+ if (map){
+ if (wvar.query != null && JSON.stringify(data).indexOf(wvar.query) == -1) {
+ refreshSingle(wvar.query);
+ } else {
+ response = formatData(data, false);
+ update(response, true);
+ $("#stTimer").attr("data-timestamp", response.fetch_timestamp);
+ }
+ $("#stText").text("");
+ clearInterval(checkLoadedTimer)
}
- $("#stText").text("");
+ }, 50)
},
error: function() {
$("#stText").text("poll error |");
- document.getElementById("timeperiod").disabled = false;
ajax_inprogress = false;
},
complete: function(request, textStatus) {
- if (!ajax_inprogress_single) {
- document.getElementById("timeperiod").disabled = false;
- }
+
clientActive = true;
//console.log("WebSockets - Resuming Websockets updates after poll.")
clearTimeout(periodical);
@@ -3802,6 +4063,7 @@ function refresh() {
});
}
+
live_data_buffer = {positions:{position:[]}}
function liveData() {
client.onConnectionLost = onConnectionLost;
@@ -3813,6 +4075,8 @@ function liveData() {
if (wvar.query && sondePrefix.indexOf(wvar.query) == -1) {
var topic = "sondes/" + wvar.query;
client.subscribe(topic);
+ client.subscribe("prediction/"+wvar.query);
+ client.subscribe("reverse-prediction/"+wvar.query);
clientTopic = [topic];
} else {
client.subscribe("sondes-new/#");
@@ -3893,7 +4157,32 @@ function liveData() {
} else {
updateReceivers(formatted_frame, single=true);
}
+ } else if (message.topic.startsWith("prediction")) {
+ var frame = JSON.parse(message.payloadString.toString());
+ var pred_data = [
+ {
+ "vehicle": frame.serial,
+ "time": frame.datetime,
+ "latitude": frame.position[1],
+ "longitude": frame.position[0],
+ "altitude": frame.altitude,
+ "ascent_rate": frame.ascent_rate,
+ "descent_rate": frame.descent_rate,
+ "burst_altitude": frame.burst_altitude,
+ "descending": frame.descending ? 1 : 0,
+ "landed": frame.landed ? 1 : 0,
+ "data": JSON.stringify(frame.data)
+ }
+ ]
+ updatePredictions(pred_data);
+ } else if (message.topic.startsWith("reverse-prediction")) {
+ var frame = JSON.parse(message.payloadString.toString());
+ var serial = frame["serial"];
+ var pred_data = {
+ }
+ pred_data[serial] = frame
+ updateLaunchPredictions(pred_data);
} else {
var frame = JSON.parse(message.payloadString.toString());
@@ -3918,7 +4207,10 @@ function liveData() {
// Interval to read in the live data buffer and update the page.
setInterval(function(){
- update(live_data_buffer);
+ if(map){
+ update(live_data_buffer);
+ }
+
live_data_buffer.positions.position=[];
}, 500)
@@ -3943,20 +4235,23 @@ function refreshSingle(serial) {
url: data_url,
dataType: "json",
success: function(data, textStatus) {
- response = formatData(data, false);
- update(response, true);
- singleRecovery(serial);
- $("#stText").text("");
+ var checkLoadedTimer = setInterval(() => {
+ if (map){
+ response = formatData(data, false);
+ update(response, true);
+ singleRecovery(serial);
+ $("#stText").text("");
+ clearInterval(checkLoadedTimer);
+ }
+ }, 50)
},
error: function() {
$("#stText").text("error |");
ajax_inprogress_single = false;
- document.getElementById("timeperiod").disabled = false;
},
complete: function(request, textStatus) {
clearTimeout(periodical_focus);
ajax_inprogress_single = false;
- document.getElementById("timeperiod").disabled = false;
}
});
}
@@ -3978,12 +4273,17 @@ function refreshSingleNew(serial) {
ajax_inprogress_single_new = true;
var data_str = "duration=3d&serial=" + serial;
-
+
+ var xhr = new XMLHttpRequest();
+
ajax_positions_single_new = $.ajax({
type: "GET",
url: newdata_url,
data: data_str,
dataType: "json",
+ xhr: function() {
+ return xhr;
+ },
success: function(data, textStatus) {
response = formatData(data, false);
update(response, true);
@@ -3994,6 +4294,20 @@ function refreshSingleNew(serial) {
complete: function(request, textStatus) {
clearTimeout(periodical_focus_new);
ajax_inprogress_single_new = false;
+ // check if we have been redirected for history - if not we can also fetch that if it exists
+ if (xhr.responseURL.includes(newdata_url)){
+ $.ajax({
+ type: "GET",
+ url: "https://sondehub-history.s3.amazonaws.com/serial/"+ encodeURIComponent(serial) +".json.gz",
+ dataType: "json",
+ success: function(data, textStatus) {
+ response = formatData(data, false);
+ update(response, true);
+ },
+ error: function() {
+ }
+ })
+ }
}
});
}
@@ -4033,7 +4347,12 @@ function refreshReceivers() {
data: data_str,
dataType: "json",
success: function(response, textStatus) {
- updateReceivers(response, single=false);
+ var checkLoadedTimer = setInterval(() => {
+ if (map){
+ updateReceivers(response, single=false);
+ clearInterval(checkLoadedTimer);
+ }
+ }, 50);
},
complete: function(request, textStatus) {
if (!offline.get("opt_hide_chase")) {
@@ -4086,7 +4405,9 @@ function singleRecovery(serial) {
data: datastr,
dataType: "json",
success: function(response, textStatus) {
- updateRecoveries(response);
+ if(!offline.get('opt_hide_recoveries')) {
+ updateRecoveries(response, true);
+ }
}
});
@@ -4099,10 +4420,15 @@ function refreshRecoveries() {
url: recovered_sondes_url,
dataType: "json",
success: function(response, textStatus) {
- updateRecoveryPane(response);
- if(!offline.get('opt_hide_recoveries')) {
- updateRecoveries(response);
+ var checkLoadedTimer = setInterval(() => {
+ if (map){
+ updateRecoveryPane(response);
+ if(!offline.get('opt_hide_recoveries')) {
+ updateRecoveries(response);
+ }
+ clearInterval(checkLoadedTimer);
}
+ }, 50);
},
error: function() {
updateRecoveryPane([]);
@@ -4129,45 +4455,6 @@ function refreshRecoveryStats() {
var ajax_predictions = null;
-function refreshPredictions() {
- if(ajax_inprogress) {
- clearTimeout(periodical_predictions);
- periodical_predictions = setTimeout(refreshPredictions, 1000);
- return;
- }
-
- ajax_predictions = $.ajax({
- type: "GET",
- url: predictions_url + encodeURIComponent(wvar.query),
- data: "",
- dataType: "json",
- success: function(response, textStatus) {
- updatePredictions(response);
- },
- error: function() {
- },
- complete: function(request, textStatus) {
- clearTimeout(periodical_predictions);
- periodical_predictions = setTimeout(refreshPredictions, 60 * 1000);
- }
- });
-
- var data_str = "duration=" + wvar.mode + "&vehicles=" + encodeURIComponent(wvar.query);
-
- ajax_predictions = $.ajax({
- type: "GET",
- url: launch_predictions_url,
- data: data_str,
- dataType: "json",
- success: function(response, textStatus) {
- updateLaunchPredictions(response);
- },
- error: function() {
- },
- complete: function(request, textStatus) {
- }
- });
-}
var periodical, periodical_focus, periodical_focus_new, periodical_receivers, periodical_listeners, periodical_recoveries;
var periodical_predictions = null;
@@ -4175,8 +4462,6 @@ var timer_seconds = 5;
function startAjax() {
- document.getElementById("timeperiod").disabled = true;
-
// prevent insane clicks to start numerous requests
clearTimeout(periodical);
clearTimeout(periodical_focus);
@@ -4234,14 +4519,17 @@ function updateCurrentPosition(lat, lon) {
} else {
currentPosition.lat = lat;
currentPosition.lon = lon;
- currentPosition.marker.addTo(map);
- currentPosition.marker.setLatLng(latlng);
+ if (!CHASE_enabled){
+ currentPosition.marker.addTo(map);
+ currentPosition.marker.setLatLng(latlng);
+ }
}
}
function updateReceiverMarker(receiver) {
var latlng = new L.LatLng(receiver.lat, receiver.lon);
+
// init a marker if the receiver doesn't already have one
if(!receiver.marker) {
@@ -4278,8 +4566,10 @@ function updateReceiverMarker(receiver) {
}
receiver.marker.bindPopup(receiver.infobox);
-
- receiverCanvas.addLayer(receiver.marker);
+ if (!offline.get("opt_hide_receivers") ){
+ receiverCanvas.addLayer(receiver.marker);
+ }
+
} else {
receiver.marker.setLatLng(latlng);
receiver.infobox = new L.popup({ autoClose: false, closeOnClick: false }).setContent(receiver.description);
@@ -4319,6 +4609,7 @@ function updateChase(r) {
dataTempEntry.gps_alt = last.uploader_position[2];
dataTempEntry.gps_lat = last.uploader_position[0];
dataTempEntry.gps_lon = last.uploader_position[1];
+ dataTempEntry.gps_heading = 90;
var date = new Date(last.ts)
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
var time = new Date(date.getTime() - userTimezoneOffset).toISOString();
@@ -4452,7 +4743,7 @@ function updateReceivers(r, single) {
i = 0;
for(; i < receivers.length;) {
var e = receivers[i];
- if(e.fresh) {
+ if(e.fresh && !offline.get("opt_hide_receivers")) {
e.fresh = false;
i++;
}
@@ -4481,6 +4772,13 @@ function updateRecoveryMarker(recovery) {
_recovery_icon = host_url + markers_url + "payload-not-recovered.png";
}
+ // Override icon if 'is planned' field exists and is true
+ if(recovery.hasOwnProperty('planned')){
+ if(recovery.planned == true){
+ _recovery_icon = host_url + markers_url + "payload-recovery-planned.png";
+ }
+ }
+
recoveryIcon = new L.icon({
iconUrl: _recovery_icon,
iconSize: [17, 19],
@@ -4500,23 +4798,36 @@ function updateRecoveryMarker(recovery) {
div = document.createElement('div');
+ _recovered_text = recovery.recovered ? " Recovered" : " Not Recovered";
+
+ // Override text is planned field exists and is true
+ if(recovery.hasOwnProperty('planned')){
+ if(recovery.planned == true){
+ _recovered_text = " Recovery Planned";
+ }
+ }
+
html = "";
- html += "
"+recovery.serial+(recovery.recovered ? " Recovered" : " Not Recovered")+"
";
+ html += "
";
html += "
";
- html += "
"+roundNumber(recovery.lat, 5) + ', ' + roundNumber(recovery.lon, 5)+"
";
+ html += "
"+format_coordinates(recovery.lat, recovery.lon, recovery.serial)+"
";
- var imp = offline.get('opt_imperial');
- var text_alt = Number((imp) ? Math.floor(3.2808399 * parseInt(recovery.alt)) : parseInt(recovery.alt)).toLocaleString("us");
- text_alt += " " + ((imp) ? 'ft':'m');
-
- html += "
Time: "+formatDate(stringToDateUTC(recovery.datetime))+"
";
- html += "
Reported by: "+recovery.recovered_by+"
";
- html += "
Notes: "+$('
').text(recovery.description).html()+"
";
- html += "
";
+ html += "
Time:
";
+ html += "
Reported by:
";
+ html += "
Notes:
";
+ html += "
";
html += "
";
div.innerHTML = html;
+ div.getElementsByClassName("recovery_text")[0].textContent = recovery.serial+_recovered_text
+ div.getElementsByClassName("recovery_time")[0].textContent = formatDate(stringToDateUTC(recovery.datetime))
+ div.getElementsByClassName("recovery_by")[0].textContent = recovery.recovered_by
+ div.getElementsByClassName("recovery_desc")[0].textContent = recovery.description
+ div.getElementsByClassName("recovery_path")[0].textContent = recovery.serial
+ div.getElementsByClassName("recovery_path")[0].onclick = function(){
+ showRecoveredMap(recovery.serial)
+ }
recovery.infobox.setContent(div);
@@ -4525,8 +4836,7 @@ function updateRecoveryMarker(recovery) {
}
}
- function updateRecoveries(r) {
-
+ function updateRecoveries(r, single=false) {
if(!r) return;
ls_recoveries = true;
@@ -4535,41 +4845,39 @@ function updateRecoveryMarker(recovery) {
var i = 0, ii = r.length;
for(; i < ii; i++) {
- var date = Date.parse(r[i].datetime);
- if (((dateNow - date) / 86400000) < 3) {
- var lat = parseFloat(r[i].lat);
- var lon = parseFloat(r[i].lon);
-
- if(lat < -90 || lat > 90 || lon < -180 || lon > 180) continue;
-
- var r_index = $.inArray(r[i].serial, recovery_names);
-
- if(r_index == -1) {
- recovery_names.push(r[i].serial);
- r_index = recovery_names.length - 1;
- recoveries[r_index] = {marker: null, infobox: null};
- }
-
- var recovery = recoveries[r_index];
- recovery.serial = r[i].serial;
- recovery.lat = lat;
- recovery.lon = lon;
- recovery.recovered_by = r[i].recovered_by;
- recovery.alt = parseFloat(r[i].alt);
- recovery.recovered = r[i].recovered;
- recovery.description = r[i].description;
- recovery.datetime = r[i].datetime;
- recovery.fresh = true;
-
- updateRecoveryMarker(recovery);
- }
+ var lat = parseFloat(r[i].lat);
+ var lon = parseFloat(r[i].lon);
+
+ if(lat < -90 || lat > 90 || lon < -180 || lon > 180) continue;
+
+ var r_index = $.inArray(r[i].serial, recovery_names);
+
+ if(r_index == -1) {
+ recovery_names.push(r[i].serial);
+ r_index = recovery_names.length - 1;
+ recoveries[r_index] = {marker: null, infobox: null};
+ }
+
+ var recovery = recoveries[r_index];
+ recovery.serial = r[i].serial;
+ recovery.lat = lat;
+ recovery.lon = lon;
+ recovery.recovered_by = r[i].recovered_by;
+ recovery.alt = parseFloat(r[i].alt);
+ recovery.recovered = r[i].recovered;
+ recovery.description = r[i].description;
+ recovery.datetime = r[i].datetime;
+ recovery.planned = r[i].planned;
+ recovery.fresh = true;
+ updateRecoveryMarker(recovery);
+
}
// clear old recovery markers
i = 0;
for(; i < recoveries.length;) {
var e = recoveries[i];
- if(e.fresh) {
+ if(e.fresh || single) {
e.fresh = false;
i++;
}
@@ -4613,9 +4921,18 @@ function updateRecoveryPane(r){
recoveries[r_index] = {marker: null, infobox: null};
}
+ _recovered_text = r[i].recovered ? " Recovered by " : " Not Recovered by ";
+
+ // Override text is planned field exists and is true
+ if(r[i].hasOwnProperty('planned')){
+ if(r[i].planned == true){
+ _recovered_text = " Recovery Planned by ";
+ }
+ }
+
html += "
";
- html += "
"+r[i].serial+(r[i].recovered ? " Recovered by " : " Not Recovered by ")+r[i].recovered_by+"
";
- html += "
"+roundNumber(lat, 5) + ', ' + roundNumber(lon, 5)+"
";
+ html += "
"+r[i].serial+(_recovered_text)+r[i].recovered_by+"
";
+ html += "
"+format_coordinates(lat, lon, r[i].serial)+"
";
var imp = offline.get('opt_imperial');
var text_alt = Number((imp) ? Math.floor(3.2808399 * parseInt(alt)) : parseInt(alt)).toLocaleString("us");
@@ -4650,7 +4967,7 @@ function updateLeaderboardPane(r){
// create a sorted list
top = Object.keys(top).map(function(key){return [key, top[key]]});
top.sort(function(a, b) {
- return a[1] < b[1]
+ return b[1] - a[1];
});
html += "
Total sondes recovered: " + recovered + "/" + total + "
";
@@ -4697,23 +5014,26 @@ function updatePredictions(r) {
if(vcallsign == "XX") continue;
if(vehicles.hasOwnProperty(vcallsign)) {
- var vehicle = vehicles[vcallsign];
-
- if(vehicle.marker.mode == "landed") {
- removePrediction(vcallsign);
- continue;
+ var vehicle = vehicles[vcallsign];
+ if(vehicle.prediction && vehicle.prediction.time == r[i].time) continue;
+ vehicle.prediction = r[i];
+ vehicle.prediction.data = $.parseJSON(r[i].data);
+
+ // Figure out local ground level.
+ if(vehicle.prediction.data.length >= 2){
+ vehicle.local_ground_asl = vehicle.prediction.data[vehicle.prediction.data.length-1]['alt'];
+ } else {
+ vehicle.local_ground_asl = 0;
}
- if(vehicle.prediction && vehicle.prediction.time == r[i].time) {
- continue;
- }
- vehicle.prediction = r[i];
- if(parseInt(vehicle.prediction.landed) === 0) {
- vehicle.prediction.data = $.parseJSON(r[i].data);
+ // Only draw prediction if the last known position of the payload was > 100m above local ground level.
+ if( (vehicle.curr_position['gps_alt']-vehicle.local_ground_asl) > 100){
redrawPrediction(vcallsign);
} else {
- removePrediction(vcallsign);
+ continue;
}
+
+
}
}
}
@@ -4742,6 +5062,8 @@ function showHorizonRings(){
if(vehicles[vcallsign].vehicle_type == "balloon"){
map.addLayer(vehicles[vcallsign].horizon_circle);
map.addLayer(vehicles[vcallsign].subhorizon_circle);
+ vehicles[vcallsign].horizon_circle.fire("move")
+ vehicles[vcallsign].subhorizon_circle.fire("move")
map.addLayer(vehicles[vcallsign].horizon_circle_title);
map.addLayer(vehicles[vcallsign].subhorizon_circle_title);
}
@@ -4759,7 +5081,7 @@ function hideTitles(){
function showTitles(){
for(var vcallsign in vehicles) {
if(vehicles[vcallsign].vehicle_type == "balloon" || vehicles[vcallsign].vehicle_type == "car"){
- vehicles[vcallsign].title = vehicles[vcallsign].marker.bindTooltip(vehicles[vcallsign]["marker"]["options"]["title"], {direction: 'center', permanent: 'true', className: 'serialtooltip'});
+ vehicles[vcallsign].title = vehicles[vcallsign].marker.bindTooltip(vehicles[vcallsign]["marker"]["options"]["title"], {direction: 'center', permanent: 'false', className: 'serialtooltip'});
}
}
}
@@ -4875,11 +5197,11 @@ function update(response, none) {
}
- if(periodical_predictions === null) refreshPredictions();
+ //if(periodical_predictions === null) refreshPredictions();
},
};
-
+ document.getElementById("spinner")?.remove();
ctx_init.run(ctx_init);
sub_to_nearby_sondes();
}
diff --git a/js/station.js b/js/station.js
index 09cade0..6ad8857 100644
--- a/js/station.js
+++ b/js/station.js
@@ -174,12 +174,22 @@ function drawHistorical (data, station) {
}
}
- var popup = L.popup();
+ var popup = new L.popup({ autoClose: false, closeOnClick: false }).setContent(serial);
+
+ if (!recovered) {
+ var marker = L.circleMarker([landing.lat, landing.lon], {fillColor: "white", color: iconColour, weight: 3, radius: 5, fillOpacity:1});
+ } else {
+ var marker = L.circleMarker([landing.lat, landing.lon], {fillColor: "grey", color: iconColour, weight: 3, radius: 5, fillOpacity:1});
+ }
+
+ marker.bindPopup(popup);
+
+ div = document.createElement('div');
html = "
";
html += "
"+serial+" ("+time+")
";
html += "
";
- html += "
"+roundNumber(landing.lat, 5) + ', ' + roundNumber(landing.lon, 5)+"
";
+ html += "
Last Position: "+format_coordinates(landing.lat, landing.lon, serial)+"
";
var imp = offline.get('opt_imperial');
var text_alt = Number((imp) ? Math.floor(3.2808399 * parseInt(landing.alt)) : parseInt(landing.alt)).toLocaleString("us");
@@ -187,40 +197,60 @@ function drawHistorical (data, station) {
html += "
Altitude: "+text_alt+"
";
html += "
Time: "+formatDate(stringToDateUTC(time))+"
";
-
- if (landing.hasOwnProperty("type")) {
- html += "
Sonde Type: " + landing.type + "
";
- };
+ html += "
Sonde Type: Unknown
"
html += "
";
- if (recovered) {
- html += "
"+(recovery_info.recovered ? "Recovered by " : "Not Recovered by ")+recovery_info.recovered_by+"
";
- html += "
Recovery time: "+formatDate(stringToDateUTC(recovery_info.datetime))+"
";
- html += "
Recovery location: "+recovery_info.position[1]+", "+recovery_info.position[0] + "
";
- html += "
Recovery notes: "+recovery_info.description+"
";
-
- html += "
";
- }
+ html += "
";
+ html += "
";
+ html += "
Reported at:
";
+ html += "
Reported by:
";
+ html += "
Notes:
";
+ html += "
";
+ html += "
";
- html += "
";
+ html += "
";
html += "
";
html += "
"
+ html += "
"
+ html += "
";
- if (landing.hasOwnProperty("uploader_callsign")) {
- html += "
Last received by: " + landing.uploader_callsign.toLowerCase() + "
";
+ div.innerHTML = html;
+
+
+ div.getElementsByClassName("recovery_path")[0].textContent = serial
+ div.getElementsByClassName("recovery_path")[0].onclick = function(){
+ showRecoveredMap(serial)
+ }
+
+ if (landing.hasOwnProperty("type")) {
+ div.getElementsByClassName("landing_sonde_type")[0].textContent = landing.type;
};
- popup.setContent(html);
+ if (landing.hasOwnProperty("uploader_callsign")) {
+ div.getElementsByClassName("landing_uploader_callsign")[0].textContent = "Last received by: " + landing.uploader_callsign.toLowerCase();
+ };
- if (!recovered) {
- var marker = L.circleMarker([landing.lat, landing.lon], {fillColor: "white", color: iconColour, weight: 3, radius: 5, fillOpacity:1});
+ if (recovered) {
+ _recovered_text = recovery_info.recovered ? " Recovered" : "Not Recovered";
+
+ // Override text is planned field exists and is true
+ if(recovery_info.hasOwnProperty('planned')){
+ if(recovery_info.planned == true){
+ _recovered_text = " Recovery Planned";
+ }
+ }
+ div.getElementsByClassName("recovery_text")[0].textContent = recovery_info.serial + _recovered_text;
+ div.getElementsByClassName("recovery_time")[0].textContent = formatDate(stringToDateUTC(recovery_info.datetime));
+ div.getElementsByClassName("recovery_by")[0].textContent = recovery_info.recovered_by;
+ div.getElementsByClassName("recovery_desc")[0].textContent = recovery_info.description;
} else {
- var marker = L.circleMarker([landing.lat, landing.lon], {fillColor: "grey", color: iconColour, weight: 3, radius: 5, fillOpacity:1});
+ div.getElementsByClassName("recovery_section")[0].style.display = "none";
}
- marker.bindPopup(popup);
+ popup.setContent(div);
+
marker.addTo(map);
marker.bringToBack();
@@ -602,26 +632,26 @@ function launchSitePredictions(times, station, properties, marker, id) {
var date = new Date();
var time = times[i].split(":");
if (time[0] != 0) {
- date.setDate(date.getDate() + (7 + time[0] - date.getDay()) % 7);
+ date.setUTCDate(date.getUTCDate() + (7 + time[0] - date.getUTCDay()) % 7);
}
date.setUTCHours(time[1]);
date.setUTCMinutes(time[2]);
- date.setSeconds(0);
- date.setMilliseconds(0);
+ date.setUTCSeconds(0);
+ date.setUTCMilliseconds(0);
// launch time 45 minutes before target time
- date.setMinutes( date.getMinutes() - 45 );
+ date.setUTCMinutes( date.getUTCMinutes() - 45 );
while (date < now) {
if (time[0] == 0) {
- date.setDate(date.getDate() + 1);
+ date.setUTCDate(date.getUTCDate() + 1);
} else {
- date.setDate(date.getDate() + 7);
+ date.setUTCDate(date.getUTCDate() + 7);
}
}
if (day > 0) {
if (time[0] == 0) {
- date.setDate(date.getDate() + day);
+ date.setUTCDate(date.getUTCDate() + day);
} else {
- date.setDate(date.getDate() + (7*day));
+ date.setUTCDate(date.getUTCDate() + (7*day));
}
}
if (count < maxCount) {
@@ -738,15 +768,24 @@ function plotPrediction (data, dates, marker, properties) {
icon: new L.NumberedDivIcon({number: dates.indexOf(data.request.launch_datetime)+1})
}).addTo(map);
+ var coords_text = format_coordinates(landingPoint.latitude, landingLongitude, "Prediction");
+
var landingTime = new Date(landingPoint.datetime);
if (properties[3] != "" && properties[4] != "") {
var landingTooltip = "
Time: " + landingTime.toLocaleString() + "
Model Dataset: " + data.request.dataset +
+ "
Prediction: " + coords_text +
"
Model Assumptions: - " + data.request.ascent_rate + "m/s ascent
- " + data.request.burst_altitude + "m burst altitude (" + properties[3] + " samples)
- " + data.request.descent_rate + "m/s descent (" + properties[4] + " samples)";
} else {
var landingTooltip = "
Time: " + landingTime.toLocaleString() + "
Model Dataset: " + data.request.dataset +
+ "
Prediction: " + coords_text +
"
Model Assumptions: - " + data.request.ascent_rate + "m/s ascent
- " + data.request.burst_altitude + "m burst altitude
- " + data.request.descent_rate + "m/s descent";
}
- plot.landingMarker.bindTooltip(landingTooltip, {offset: [13,-28]});
+
+ plot.landingMarker.bindPopup(landingTooltip, { autoClose: false, closeOnClick: false })
+ .on('click', function (e) {
+ this.openPopup();
+ });
+
}
function showPrediction(url) {
@@ -917,6 +956,7 @@ function generateLaunchSites() {
}
popupContent += "
Know when this site launches? Contribute
here ";
+ popupContent += "
Site Code: " + key;
// Generate view historical button
popupContent += "
Historical ";
diff --git a/js/xdata.js b/js/xdata.js
index 5377d11..49ba6fd 100644
--- a/js/xdata.js
+++ b/js/xdata.js
@@ -592,6 +592,37 @@ function parseSKYDEW(xdata) {
return _output
}
+function parseKnmiTachometer(xdata) {
+ // KNMI Tachometer for Vaisala OIF411
+ //
+ // Sample data: 80022B5A1EE4001384A407F8 (length = 24 characters)
+
+ // Run some checks over the input
+ if(xdata.length != 24){
+ // Invalid dataset
+ return {};
+ }
+
+ if(xdata.substr(0,2) !== '80'){
+ // Not a KNMI Tachometer (shouldn't get here)
+ return {};
+ }
+
+ var _output = {};
+
+ // uptime (in seconds) of the arduino tachometer board
+ _output['tacho_uptime'] = (parseInt(xdata.substr(4,8),16) * 8 / 1000000).toFixed();
+
+ // time the Vaisala OIF411 motor needs to make 400 rounds
+ _delta = parseInt(xdata.substr(12,8),16) * 8 / 1000000;
+ _output['tacho_delta'] = _delta.toFixed(3);
+
+ // calculated rounds per second
+ _output['tacho_rps'] = (400 / _delta).toFixed(3);
+
+ return _output
+}
+
function parseXDATA(data, pressure, temperature){
// Accept an XDATA string, or multiple XDATA entries, delimited by '#'
// Attempt to parse each one, and return an object
@@ -683,9 +714,10 @@ function parseXDATA(data, pressure, temperature){
// POPS
if (!_instruments.includes("POPS")) _instruments.push('POPS');
} else if (_instrument === '80'){
- // Unknown!
- //console.log("Saw unknown XDATA instrument 0x80.")
- }else {
+ // KNMI Tachometer
+ _xdata_temp = parseKnmiTachometer(_current_xdata);
+ _output = Object.assign(_output,_xdata_temp);
+ } else {
// Unknown!
}
diff --git a/service-worker.js b/service-worker.js
deleted file mode 100644
index fc7d456..0000000
--- a/service-worker.js
+++ /dev/null
@@ -1,73 +0,0 @@
-self.addEventListener('install', function(event) {
- event.waitUntil(
- caches.open("{VER}").then(function(cache) {
- return cache.addAll(
- [
- '/css/mobile.css',
- '/css/leaflet.css',
- '/css/leaflet.fullscreen.css',
- '/js/leaflet.js',
- '/js/Leaflet.fullscreen.min.js',
- '/js/L.Terminator.js',
- '/js/mobile.js',
- '/js/rbush.js',
- '/js/leaflet.canvas-markers.js',
- '/js/pwa.js',
- '/js/init_plot.js',
- '/img/markers/antenna-green.png',
- '/img/markers/balloon-blue.png',
- '/img/markers/balloon-cyan.png',
- '/img/markers/balloon-green.png',
- '/img/markers/balloon-orange.png',
- '/img/markers/balloon-purple.png',
- '/img/markers/balloon-red.png',
- '/img/markers/balloon-yellow.png',
- '/img/markers/car-blue.png',
- '/img/markers/car-green.png',
- '/img/markers/car-red.png',
- '/img/markers/car-yellow.png',
- '/img/markers/parachute-yellow.png',
- '/img/markers/parachute-blue.png',
- '/img/markers/parachute-cyan.png',
- '/img/markers/parachute-green.png',
- '/img/markers/parachute-orange.png',
- '/img/markers/parachute-purple.png',
- '/img/markers/parachute-red.png',
- '/img/markers/payload-blue.png',
- '/img/markers/payload-cyan.png',
- '/img/markers/payload-green.png',
- '/img/markers/payload-not-recovered.png',
- '/img/markers/payload-orange.png',
- '/img/markers/payload-purple.png',
- '/img/markers/payload-recovered.png',
- '/img/markers/payload-red.png',
- '/img/markers/payload-yellow.png',
- '/img/markers/target-blue.png',
- '/img/markers/target-cyan.png',
- '/img/markers/target-green.png',
- '/img/markers/target-orange.png',
- '/img/markers/target-purple.png',
- '/img/markers/target-red.png',
- '/img/markers/target-yellow.png',
- '/img/markers/shadow.png',
- '/img/markers/balloon-pop.png',
- '/img/hab-spinner.gif',
- '/img/marker-you.gif',
- '/img/sondehub_logo.gif',
- '/favicon.ico',
- '/font/HabitatFont.woff',
- '/font/Roboto-regular.woff',
- '/index.html'
- ]
- );
- })
- );
-});
-
-self.addEventListener('fetch', function (event) {
- event.respondWith(
- caches.match(event.request).then(function (response) {
- return response || fetch(event.request);
- }),
- );
-});
\ No newline at end of file
diff --git a/service-worker.template.js b/service-worker.template.js
new file mode 100644
index 0000000..82e6ce6
--- /dev/null
+++ b/service-worker.template.js
@@ -0,0 +1,62 @@
+self.addEventListener('install', function(event) {
+ event.waitUntil(
+ caches.open("{VER}").then(function(cache) {
+ return cache.addAll(
+ [
+ '/css/base.css',
+ '/css/skeleton.css',
+ '/css/layout.css',
+ '/css/habitat-font.css',
+ '/css/main.css',
+ '/css/leaflet.css',
+ '/css/leaflet.fullscreen.css',
+ '/css/skewt.css',
+ '/js/skewt.js',
+ '/js/aws-sdk-2.1029.0.min.js',
+ '/js/leaflet.js',
+ '/js/Leaflet.fullscreen.min.js',
+ '/js/L.Terminator.js',
+ '/js/L.TileLayer.NoGap.js',
+ '/js/paho-mqtt.js',
+ '/js/jquery-1.12.4-min.js',
+ '/js/iscroll.js',
+ '/js/chasecar.lib.js',
+ '/js/sondehub.js',
+ '/js/app.js',
+ '/js/colour-map.js',
+ '/js/xdata.js',
+ '/js/station.js',
+ '/js/format.js',
+ '/js/rbush.js',
+ '/js/pwa.js',
+ '/js/_jquery.flot.js',
+ '/js/plot_config.js',
+ '/img/markers/balloon.svg',
+ '/img/markers/car.svg',
+ '/img/markers/parachute.svg',
+ '/img/markers/payload.svg',
+ '/img/markers/payload-not-recovered.png',
+ '/img/markers/payload-recovered.png',
+ '/img/markers/target.svg',
+ '/img/markers/shadow.png',
+ '/img/markers/balloon-pop.png',
+ '/img/hab-spinner.gif',
+ '/img/sondehub_au.png',
+ '/favicon.ico',
+ '/font/HabitatFont.woff',
+ '/font/Roboto-regular.woff',
+ '/index.html',
+ '/'
+ ]
+ );
+ })
+ );
+});
+
+self.addEventListener('fetch', function (event) {
+ event.respondWith(
+ caches.match(event.request).then(function (response) {
+ return response || fetch(event.request);
+ }),
+ );
+});
\ No newline at end of file
diff --git a/tools/pngout.exe b/tools/pngout.exe
deleted file mode 100755
index c72d567..0000000
Binary files a/tools/pngout.exe and /dev/null differ
diff --git a/tools/yuicompressor-2.4.8.jar b/tools/yuicompressor-2.4.8.jar
deleted file mode 100755
index a1cf0a0..0000000
Binary files a/tools/yuicompressor-2.4.8.jar and /dev/null differ