From df6a468e21dbbd64b39a1ce6a8ed82b498a29590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 17:59:18 +0100 Subject: [PATCH 01/18] WiFi support for configuration --- .gitignore | 5 +- data_embed/index.html | 132 +++++ data_embed/js.js | 42 ++ data_embed/style.css | 843 +++++++++++++++++++++++++++++ include/taskWebServer.h | 36 ++ platformio.ini | 10 +- src/TTGO_T-Beam_LoRa_APRS.ino | 137 ++++- src/TTGO_T-Beam_LoRa_APRS_config.h | 13 +- src/taskWebServer.cpp | 192 +++++++ tools/buildscript_versioning.py | 39 ++ tools/compress_assets.py | 13 + 11 files changed, 1433 insertions(+), 29 deletions(-) create mode 100644 data_embed/index.html create mode 100644 data_embed/js.js create mode 100644 data_embed/style.css create mode 100644 include/taskWebServer.h create mode 100644 src/taskWebServer.cpp create mode 100644 tools/buildscript_versioning.py create mode 100644 tools/compress_assets.py diff --git a/.gitignore b/.gitignore index 497a39a..52a4746 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ CMakeLists.txt CMakeListsPrivate.txt CMakeListsUser.txt -cmake-build-* \ No newline at end of file +cmake-build-* +/include/version.h +/data_embed/*.out +/src/TTGO_T-Beam_LoRa_APRS.ino.cpp diff --git a/data_embed/index.html b/data_embed/index.html new file mode 100644 index 0000000..bbcbbb6 --- /dev/null +++ b/data_embed/index.html @@ -0,0 +1,132 @@ + + + + + + TTGO-T-Beam-LoRa-APRS <!--VERSION--> + + + + + +
+
+
+

WiFi Settings

+
+
+
+
+
+
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+

APRS Settings

+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+
+
+
+
+

Actions

+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ + + diff --git a/data_embed/js.js b/data_embed/js.js new file mode 100644 index 0000000..abe76a7 --- /dev/null +++ b/data_embed/js.js @@ -0,0 +1,42 @@ +/**/ +function scanWifi() { + let scanBtn = document.getElementById('scan_wifi_btn'); + let wifiListContainer = document.getElementById("wifi_list"); + wifiListContainer.innerHTML = 'Scanning...'; + scanBtn.disabled = true; + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + scanBtn.disabled = false; + if (this.readyState == 4 && this.status == 200) { + wifiListContainer.innerHTML = this.responseText; + const networks_found_list = document.querySelector('#networks_found_list'); + + networks_found_list.addEventListener('change', event => { + document.getElementById('wifi_ssid').value = networks_found_list.value; + }); + } + }; + xhttp.open("GET", "/scan_wifi", true); + xhttp.send(); +} + +window.onload = function () { + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + const response = JSON.parse(this.responseText); + for (const [key, value] of Object.entries(response)) { + let element = document.getElementById(key); + if (element){ + if (element.type && element.type == "checkbox"){ + element.checked = value; + } else { + element.value = value; + } + } + } + } + }; + xhttp.open("GET", "/cfg", true); + xhttp.send(); +}; \ No newline at end of file diff --git a/data_embed/style.css b/data_embed/style.css new file mode 100644 index 0000000..53b15b4 --- /dev/null +++ b/data_embed/style.css @@ -0,0 +1,843 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} + +/* +* Barebones V3 +* Copyright 2019 Steve Cochran +* +* Based of Skeleton by Dave Gamache +* +* Free to use under the MIT license. +*/ + +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Media Breakpoints +- Variables +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + +/* ENV Variables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* Media breakpoint variables for use in media queries +* Note: this section is currently commented out pending release of +* final CSS env() spec +* Breakpoints based on +* https://medium.freecodecamp.org/the-100-correct-way-to-do-css-breakpoints-88d6a5ba1862 +* +*/ + + + +/* CSS Variables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +html { + + /* default theme: light background, dark text, blue accent */ + --theme-hue: 0; /* white */ + --accent-hue: 194; /* blue */ + + --text-color-richer: hsl(var(--theme-hue), 0%, 5%); /* #0d0d0d */ + --text-color-normal: hsl(var(--theme-hue), 0%, 13%); /* #222222 text color; button:hover:focus color */ + --text-color-softer: hsl(var(--theme-hue), 0%, 33%); /* #555555 button color; button:hover border */ + + --accent-color: hsl(var(--accent-hue), 86%, 57%); /* #33C3F0 link; button-primary bg+border; textarea,select:focus border */ + --accent-color-hover: hsl(var(--accent-hue), 76%, 49%); /* #1EAEDB link hover; button-primary:hover:focus bg+border */ + + --border-color: hsl(var(--theme-hue), 0%, 73%); /* #bbbbbb button border */ + --border-color-softer: hsl(var(--theme-hue), 0%, 82%); /* #d1d1d1 textarea,select,code,td,hr border */ + + --background-color: white; /* transparent body background; textarea,select background */ + --background-color-softer: hsl(var(--theme-hue), 0%, 95%); + --code-background: hsl(var(--theme-hue), 0%, 95%); /* #f1f1f1 code background*/ + + --button-primary-color: white; + + + /* Note: Skeleton was based off a 10px font sizing for REM */ + /* 62.5% of typical 16px browser default = 10px */ + --base-font-size: 62.5%; + + /* Grid Defaults - default to match orig skeleton settings */ + --grid-max-width: 960px; +} + +/* Dark Theme + Note: prefers-color-scheme selector support is still limited, but + included for future and an example of defining a different base 'theme' +*/ +@media (prefers-color-scheme: dark) { + :html { + /* dark theme: light background, dark text, blue accent */ + --theme-hue: 0; /* black */ + --accent-hue: 194; /* blue */ + + --text-color-richer: hsl(var(--theme-hue), 0%, 95%); /* */ + --text-color-normal: hsl(var(--theme-hue), 0%, 80%); /* text color; button:hover:focus color */ + --text-color-softer: hsl(var(--theme-hue), 0%, 67%); /* button color; button:hover border */ + + --accent-color: hsl(var(--accent-hue), 76%, 49%); /* link; button-primary bg+border; textarea,select:focus border */ + --accent-color-hover: hsl(var(--accent-hue), 86%, 57%); /* link hover; button-primary:hover:focus bg+border */ + + --border-color: hsl(var(--theme-hue), 0%, 27%); /* button border */ + --border-color-softer: hsl(var(--theme-hue), 0%, 20%); /* textarea,select,code,td,hr border */ + + --background-color: hsl(var(--theme-hue), 0%, 12%); /* body background; textarea,select background */ + --background-color-softer: hsl(var(--theme-hue), 0%, 18%); + --code-background: hsl(var(--theme-hue), 0%, 5%); /* code background*/ + + --button-primary-color: white; + } + + img.value-img { + filter: invert(0.8); + } + /* TODO - test dialing back image intensity on dark background + img { + opacity: .80; + transition: opacity .5s ease-in-out; + } + img:hover { + opacity: 1; + } + */ +} + + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* CSS Grid depends much more on CSS than HTML, so there is less boilerplate + than with skeleton. Only basic 1-4 column grids are included. + Any additional needs should be made using custom CSS directives */ + + +.grid-container { + position: relative; + max-width: var(--grid-max-width); + margin: 0 auto; + padding: 20px; + text-align: center; + display: grid; + grid-gap: 20px; + gap: 20px; + + /* by default use min 200px wide columns auto-fit into width */ + grid-template-columns: minmax(200px, 1fr); +} + +/* grids to 3 columns above mobile sizes */ +@media (min-width: 600px) { + .grid-container { + grid-template-columns: repeat(3, 1fr); + padding: 10px 0; + } + + /* basic grids */ + .grid-container.fifths { + grid-template-columns: repeat(5, 1fr); + } + .grid-container.quarters { + grid-template-columns: repeat(4, 1fr); + } + .grid-container.thirds { + grid-template-columns: repeat(3, 1fr); + } + .grid-container.halves { + grid-template-columns: repeat(2, 1fr); + } + .grid-container.full { + grid-template-columns: 1fr; + } + +} + + + + + + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +html { + font-size: var(--base-font-size); + scroll-behavior: smooth; +} +body { + font-size: 1.6rem; /* changed from 15px in orig skeleton */ + line-height: 1.6; + font-weight: 400; + font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: var(--text-color-normal); + background-color: var(--background-color);; +} + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 2rem; + font-weight: 300; } +h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } +h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } +h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } +h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } + +/* Larger than phablet */ +@media (min-width: 600px) { + h1 { font-size: 5.0rem; } + h2 { font-size: 4.2rem; } + h3 { font-size: 3.6rem; } + h4 { font-size: 3.0rem; } + h5 { font-size: 2.4rem; } + h6 { font-size: 1.5rem; } +} + +p { + margin-top: 0; } + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: var(--accent-color); } +a:hover { + color: var(--accent-color-hover); } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: var(--text-color-softer); + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid var(--border-color); + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: var(--text-color-normal); + border-color: var(--text-color-softer); + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: var(--button-primary-color); + background-color: var(--accent-color); + border-color: var(--accent-color); } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: var(--button-primary-color); + background-color: var(--accent-color-hover); + border-color: var(--accent-color-hover); } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: var(--background-color); + border: 1px solid var(--border-color-softer); + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; } +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +input[type="button"], +input[type="submit"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid var(--accent-color); + outline: 0; } +label, +legend { + display: block; + margin-bottom: .5rem; + font-weight: 600; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, ul ol, ol ol, ol ul { + font-size: 100%; + margin: 1rem 0 1rem 3rem; + color: var(--text-color-softer); +} +li { + margin-bottom: 0.5rem; } + + +/* Code +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +code { + padding: .2rem .5rem; + margin: 0 .2rem; + font-size: 90%; + white-space: nowrap; + background: var(--code-background); + border: 1px solid var(--border-color-softer); + border-radius: 4px; } +pre > code { + display: block; + padding: 1rem 1.5rem; + white-space: pre; + overflow: auto; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid var(--border-color-softer); } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 1rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 1.5rem; } +pre, +blockquote, +dl, +figure, +table, +p, +ul, +ol, +form { + margin-bottom: 2.5rem; } + + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } +.u-align-left { + text-align: left; } +.u-align-right { + text-align: right; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid var(--border-color-softer); } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile (default point when grid becomes active) */ +@media (min-width: 600px) { +} + +/* Larger than phablet */ +@media (min-width: 900px) { + .container { + max-width: 900px; + } +} + +/* Larger than tablet */ +@media (min-width: 1200px) {} + +footer { +text-align: center +} + +.container { +position: relative; +margin: 0 auto; +} + +section { + border-radius: 4px; + border: 1px solid var(--border-color); + margin-top: 5px; + padding: 5px; +} \ No newline at end of file diff --git a/include/taskWebServer.h b/include/taskWebServer.h new file mode 100644 index 0000000..a904511 --- /dev/null +++ b/include/taskWebServer.h @@ -0,0 +1,36 @@ +#include +#include "TTGO_T-Beam_LoRa_APRS_config.h" +#include +#include +#include +#include + +#define ENABLE_PREFERENCES + +extern Preferences preferences; +// MAX 15 chars for preferenece key!!! +static const char *const PREF_APRS_CALLSIGN = "aprs_callsign"; +static const char *const PREF_APRS_RELAY_PATH = "aprs_relay_path"; +static const char *const PREF_APRS_RELAY_PATH_INIT = "aprs_relay_init"; +static const char *const PREF_APRS_SYMBOL_TABLE = "aprs_s_table"; +static const char *const PREF_APRS_SYMBOL = "aprs_symbol"; +static const char *const PREF_APRS_COMMENT = "aprs_comment"; +static const char *const PREF_APRS_COMMENT_INIT = "aprs_comm_init"; +static const char *const PREF_APRS_SHOW_ALTITUDE = "aprs_alt"; +static const char *const PREF_APRS_SHOW_ALTITUDE_INIT = "aprs_alt_init"; +static const char *const PREF_APRS_SHOW_BATTERY = "aprs_batt"; +static const char *const PREF_APRS_SHOW_BATTERY_INIT = "aprs_batt_init"; +static const char *const PREF_APRS_LATITUDE_PRESET = "aprs_lat_p"; +static const char *const PREF_APRS_LATITUDE_PRESET_INIT = "aprs_lat_p_init"; +static const char *const PREF_APRS_LONGITUDE_PRESET = "aprs_lon_p"; +static const char *const PREF_APRS_LONGITUDE_PRESET_INIT = "aprs_lon_p_init"; +static const char *const PREF_APRS_FIXED_BEACON_PRESET = "aprs_fixed_beac"; +static const char *const PREF_APRS_FIXED_BEACON_PRESET_INIT = "aprs_fix_b_init"; +static const char *const PREF_APRS_FIXED_BEACON_INTERVAL_PRESET = "aprs_fb_interv"; +static const char *const PREF_APRS_FIXED_BEACON_INTERVAL_PRESET_INIT = "aprs_fb_in_init"; + +typedef struct { + String callsign; +} tWebServerCfg; + +[[noreturn]] void taskWebServer(void *parameter); \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 92878c7..dcadf34 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,7 +14,15 @@ board = ttgo-t-beam framework = arduino monitor_speed = 115200 build_flags = -Wl,--gc-sections,--relax -lib_deps = +board_build.partitions = no_ota.csv +board_build.embed_files = + data_embed/index.html.out + data_embed/style.css.out + data_embed/js.js.out +extra_scripts = + pre:tools/buildscript_versioning.py + pre:tools/compress_assets.py +lib_deps = RadioHead TinyGPSPlus #DHT sensor library for ESPx diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index f224516..78de1f8 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -25,7 +25,10 @@ #ifdef KISS_PROTOCOL #include "taskTNC.h" #endif - +#ifdef ENABLE_WIFI + #include "taskWebServer.h" +#endif +#include "version.h" // I2C LINES #define I2C_SDA 21 @@ -66,6 +69,16 @@ boolean gps_state = true; boolean key_up = true; boolean t_lock = false; boolean fixed_beacon_enabled = false; +#ifdef SHOW_ALT +boolean showAltitude = true; +#else +boolean showAltitude = false; +#endif +#ifdef SHOW_BATT +boolean showBattery = true; +#else +boolean showBattery = false; +#endif // Variables and Constants String loraReceivedFrameString = ""; //data on buff is copied to this string @@ -115,6 +128,11 @@ float average_course[ANGLE_AVGS]; float avg_c_y, avg_c_x; uint8_t txPower = TXdbmW; +#ifdef ENABLE_WIFI +tWebServerCfg webServerCfg; +#endif + + static const adc_atten_t atten = ADC_ATTEN_DB_6; static const adc_unit_t unit = ADC_UNIT_1; @@ -153,10 +171,9 @@ void prepareAPRSFrame(){ double Tspeed=0, Tcourse=0; String Speedx, Coursex; int i; - #ifdef SHOW_ALT - String Altx; - int Talt; - #endif + + String Altx; + int Talt; Tlat=gps.location.lat(); Tlon=gps.location.lng(); @@ -183,31 +200,31 @@ void prepareAPRSFrame(){ outString += ">APLM0:!"; } - if(gps_state && gps.location.isValid()){ + if(gps_state && gps.location.isValid()) { outString += aprsSymbolTable; ax25_base91enc(helper_base91, 4, aprs_lat); - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { outString += helper_base91[i]; } ax25_base91enc(helper_base91, 4, aprs_lon); - for (i=0; i<4; i++) { + for (i = 0; i < 4; i++) { outString += helper_base91[i]; } outString += aprsSymbol; - ax25_base91enc(helper_base91, 1, (uint32_t) Tcourse/4 ); + ax25_base91enc(helper_base91, 1, (uint32_t) Tcourse / 4); outString += helper_base91[0]; - ax25_base91enc(helper_base91, 1, (uint32_t) (log1p(Tspeed)/0.07696)); + ax25_base91enc(helper_base91, 1, (uint32_t) (log1p(Tspeed) / 0.07696)); outString += helper_base91[0]; outString += "H"; - #ifdef SHOW_ALT - Talt=gps.altitude.meters() * 3.28d; + if (showAltitude) { + Talt = gps.altitude.meters() * 3.28d; Altx = Talt; outString += "/A="; - for (i = 0; i < (6-Altx.length()); ++i) { + for (i = 0; i < (6 - Altx.length()); ++i) { outString += "0"; } outString += Talt; - #endif + } }else{ outString += aprsLonPreset; outString += aprsSymbolTable; @@ -217,11 +234,11 @@ void prepareAPRSFrame(){ outString += aprsComment; - #ifdef SHOW_BATT // battery is not frame part move after comment + if (showBattery) { outString += " Batt="; outString += String(BattVolts, 2); outString += ("V"); - #endif + } #ifdef KISS_PROTOCOL sendToTNC(outString); @@ -373,8 +390,77 @@ void sendTelemetryFrame() { // + SETUP --------------------------------------------------------------+// void setup(){ + #ifdef DIGI_PATH + relay_path = DIGI_PATH; + #else + relay_path = ""; + #endif #ifdef FIXED_BEACON_EN - fixed_beacon_enabled = true; + fixed_beacon_enabled = true; + #endif + + #ifdef ENABLE_PREFERENCES + preferences.begin("cfg", false); + aprsSymbolTable = preferences.getString(PREF_APRS_SYMBOL_TABLE); + if (aprsSymbolTable.isEmpty()){ + preferences.putString(PREF_APRS_SYMBOL_TABLE, APRS_SYMBOL_TABLE); + aprsSymbolTable = preferences.getString(PREF_APRS_SYMBOL_TABLE); + } + + aprsSymbol = preferences.getString(PREF_APRS_SYMBOL); + if (aprsSymbol.isEmpty()){ + preferences.putString(PREF_APRS_SYMBOL, APRS_SYMBOL); + aprsSymbol = preferences.getString(PREF_APRS_SYMBOL, APRS_SYMBOL); + } + + if (!preferences.getBool(PREF_APRS_COMMENT_INIT)){ + preferences.putBool(PREF_APRS_COMMENT_INIT, true); + preferences.putString(PREF_APRS_COMMENT, MY_COMMENT); + } + aprsComment = preferences.getString(PREF_APRS_COMMENT); + + if (!preferences.getBool(PREF_APRS_RELAY_PATH_INIT)){ + preferences.putBool(PREF_APRS_RELAY_PATH_INIT, true); + preferences.putString(PREF_APRS_RELAY_PATH, DIGI_PATH); + } + relay_path = preferences.getString(PREF_APRS_RELAY_PATH); + + if (!preferences.getBool(PREF_APRS_SHOW_ALTITUDE_INIT)){ + preferences.putBool(PREF_APRS_SHOW_ALTITUDE_INIT, true); + preferences.putBool(PREF_APRS_SHOW_ALTITUDE, showAltitude); + } + showAltitude = preferences.getBool(PREF_APRS_SHOW_ALTITUDE); + + if (!preferences.getBool(PREF_APRS_SHOW_BATTERY_INIT)){ + preferences.putBool(PREF_APRS_SHOW_BATTERY_INIT, true); + preferences.putBool(PREF_APRS_SHOW_BATTERY, showBattery); + } + showBattery = preferences.getBool(PREF_APRS_SHOW_BATTERY); + + if (!preferences.getBool(PREF_APRS_LATITUDE_PRESET_INIT)){ + preferences.putBool(PREF_APRS_LATITUDE_PRESET_INIT, true); + preferences.putString(PREF_APRS_LATITUDE_PRESET, LATIDUDE_PRESET); + } + aprsLatPreset = preferences.getString(LATIDUDE_PRESET); + + if (!preferences.getBool(PREF_APRS_LONGITUDE_PRESET_INIT)){ + preferences.putBool(PREF_APRS_LONGITUDE_PRESET_INIT, true); + preferences.putString(PREF_APRS_LONGITUDE_PRESET, LONGITUDE_PRESET); + } + aprsLonPreset = preferences.getString(PREF_APRS_LONGITUDE_PRESET); + + if (!preferences.getBool(PREF_APRS_FIXED_BEACON_PRESET_INIT)){ + preferences.putBool(PREF_APRS_FIXED_BEACON_PRESET_INIT, true); + preferences.putBool(PREF_APRS_FIXED_BEACON_PRESET, fixed_beacon_enabled); + } + fixed_beacon_enabled = preferences.getBool(PREF_APRS_FIXED_BEACON_PRESET); + + if (!preferences.getBool(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET_INIT)){ + preferences.putBool(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET_INIT, true); + preferences.putInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET, fix_beacon_interval/1000); + } + fix_beacon_interval = preferences.getInt(PREF_APRS_FIXED_BEACON_PRESET) * 1000; + #endif for (int i=0;i RUNNER, "b" => BICYCLE, "<" => MOTORCYCLE, "R" => Recreation Vehicle -#define MY_COMMENT "LoRa tracker" // add your coment here - if empty then no comment is sent -//#define SHOW_ALT // send Altitude in frame +#define MY_COMMENT "TTGO LoRa APRS Tracker" // add your coment here - if empty then no comment is sent +#define SHOW_ALT // send Altitude in frame #define SHOW_BATT // send battery voltage at the end of comment (we need beggining for QSY message format) #define SHOW_RX_PACKET // uncomment to show received LoRa APS packets for the time given below -#define SHOW_RX_TIME 10000 // show RX packet for milliseconds (5000 = 5secs) +#define SHOW_RX_TIME 2000 // show RX packet for milliseconds (5000 = 5secs) #define TXFREQ 433.775 // Transmit frequency in MHz #define TXdbmW 20 // Transmit power in dBm 17-50mW, 18-63mW, 19-80mW, 20-100mW //#define SHOW_GPS_DATA // uncomment to show on serial port, received data from GPS and debug information @@ -28,6 +28,7 @@ //#define LOCAL_KISS_ECHO // echoing KISS frame back #define T_BEAM_V1_0 // if enabled t-beam v1.0 disabled t-beam V.0.7 //#define KISS_DEBUG +#define ENABLE_WIFI #define MAX_TIME_TO_NEXT_TX 360000L // TRANSMIT INTERVAL set here MAXIMUM time in ms(!) for smart beaconing - minimum time is always 1 min = 60 secs = 60000L !!! #define FIX_BEACON_INTERVAL 1800000L // Fixed beacon interwal (when GPS is disabled and FIXED_BEACON_EN is enabled) 30min default diff --git a/src/taskWebServer.cpp b/src/taskWebServer.cpp new file mode 100644 index 0000000..d302ffa --- /dev/null +++ b/src/taskWebServer.cpp @@ -0,0 +1,192 @@ +#include "taskWebServer.h" +/** + * @see board_build.embed_txtfiles in platformio.ini + */ +extern const char web_index_html[] asm("_binary_data_embed_index_html_out_start"); +extern const char web_index_html_end[] asm("_binary_data_embed_index_html_out_end"); +extern const char web_style_css[] asm("_binary_data_embed_style_css_out_start"); +extern const char web_style_css_end[] asm("_binary_data_embed_style_css_out_end"); +extern const char web_js_js[] asm("_binary_data_embed_js_js_out_start"); +extern const char web_js_js_end[] asm("_binary_data_embed_js_js_out_end"); + + +String apSSID = ""; +String apPassword = "xxxxxxxxxx"; +WebServer server(80); +Preferences preferences; + +void sendCacheHeader() { server.sendHeader("Cache-Control", "max-age=3600"); } +void sendGzipHeader() { server.sendHeader("Content-Encoding", "gzip"); } + +String jsonEscape(String s){ + s.replace("\"", "\\\""); + s.replace("\\", "\\\\"); + return s; +} + +String jsonLineFromPreferenceString(const char *preferenceName, bool last=false){ + return String("\"") + preferenceName + "\":\"" + jsonEscape(preferences.getString(preferenceName)) + (last ? + R"(")" : + R"(",)"); +} +String jsonLineFromPreferenceBool(const char *preferenceName, bool last=false){ + return String("\"") + preferenceName + "\":" + (preferences.getBool(preferenceName) ? "true" : "false") + (last ? + R"()" : + R"(,)"); +} +String jsonLineFromPreferenceInt(const char *preferenceName, bool last=false){ + return String("\"") + preferenceName + "\":" + (preferences.getInt(preferenceName)) + (last ? + R"()" : + R"(,)"); +} + +void handle_NotFound(){ + sendCacheHeader(); + server.send(404, "text/plain", "Not found"); +} + +void handle_Index() { + sendGzipHeader(); + server.send_P(200, "text/html", web_index_html, web_index_html_end - web_index_html); +} + +void handle_Style() { + sendCacheHeader(); + sendGzipHeader(); + server.send_P(200, "text/css", web_style_css, web_style_css_end - web_style_css); +} + +void handle_Js() { + sendCacheHeader(); + sendGzipHeader(); + server.send_P(200, "text/javascript", web_js_js, web_js_js_end-web_js_js); +} + +void handle_ScanWifi() { + String listResponse = R"("; + server.send(200,"text/html", listResponse); +} + +void handle_SaveWifiCfg() { + if (!server.hasArg("wifi_ssid") || !server.hasArg("wifi_password")){ + server.send(500, "text/plain", "Invalid request"); + } + if (!server.arg("wifi_ssid").length() || !server.arg("wifi_password").length()){ + server.send(403, "text/plain", "Empty SSID or Password"); + } + + preferences.putString("wifi_ssid", server.arg("wifi_ssid")); + preferences.putString("wifi_password", server.arg("wifi_password")); + + server.sendHeader("Location", "/"); + server.send(302,"text/html", ""); +} + +void handle_Reboot() { + server.sendHeader("Location", "/"); + server.send(302,"text/html", ""); + ESP.restart(); +} + +void handle_Restore() { + server.sendHeader("Location", "/"); + server.send(302,"text/html", ""); + preferences.clear(); + preferences.end(); + ESP.restart(); +} + +void handle_Cfg() { + String jsonData = "{"; + jsonData += R"("wifi_ssid":")" + jsonEscape(preferences.getString("wifi_ssid")) + R"(",)"; + jsonData += R"("wifi_password":")" + jsonEscape((preferences.getString("wifi_password").isEmpty() ? String("") : "*")) + R"(",)"; + jsonData += jsonLineFromPreferenceString(PREF_APRS_CALLSIGN); + jsonData += jsonLineFromPreferenceString(PREF_APRS_RELAY_PATH); + jsonData += jsonLineFromPreferenceString(PREF_APRS_SYMBOL_TABLE); + jsonData += jsonLineFromPreferenceString(PREF_APRS_SYMBOL); + jsonData += jsonLineFromPreferenceString(PREF_APRS_COMMENT); + jsonData += jsonLineFromPreferenceString(PREF_APRS_LATITUDE_PRESET); + jsonData += jsonLineFromPreferenceString(PREF_APRS_LONGITUDE_PRESET); + jsonData += jsonLineFromPreferenceInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET); + jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_BATTERY); + jsonData += jsonLineFromPreferenceBool(PREF_APRS_FIXED_BEACON_PRESET); + jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_ALTITUDE, true); + jsonData += "}"; + server.send(200,"application/json", jsonData); +} + +void handle_SaveAPRSCfg() { + if (server.hasArg(PREF_APRS_CALLSIGN) && !server.arg(PREF_APRS_CALLSIGN).isEmpty()){ + preferences.putString(PREF_APRS_CALLSIGN, server.arg(PREF_APRS_CALLSIGN)); + } + if (server.hasArg(PREF_APRS_SYMBOL_TABLE) && !server.arg(PREF_APRS_SYMBOL_TABLE).isEmpty()){ + preferences.putString(PREF_APRS_SYMBOL_TABLE, server.arg(PREF_APRS_SYMBOL_TABLE)); + } + if (server.hasArg(PREF_APRS_SYMBOL) && !server.arg(PREF_APRS_SYMBOL).isEmpty()){ + preferences.putString(PREF_APRS_SYMBOL, server.arg(PREF_APRS_SYMBOL)); + } + if (server.hasArg(PREF_APRS_RELAY_PATH)){ + preferences.putString(PREF_APRS_RELAY_PATH, server.arg(PREF_APRS_RELAY_PATH)); + } + if (server.hasArg(PREF_APRS_COMMENT)){ + preferences.putString(PREF_APRS_COMMENT, server.arg(PREF_APRS_COMMENT)); + } + if (server.hasArg(PREF_APRS_LATITUDE_PRESET)){ + preferences.putString(PREF_APRS_LATITUDE_PRESET, server.arg(PREF_APRS_LATITUDE_PRESET)); + } + if (server.hasArg(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET)){ + preferences.putInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET, server.arg(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET).toInt()); + } + if (server.hasArg(PREF_APRS_LONGITUDE_PRESET)){ + preferences.putString(PREF_APRS_LONGITUDE_PRESET, server.arg(PREF_APRS_LONGITUDE_PRESET)); + } + preferences.putBool(PREF_APRS_SHOW_BATTERY, server.hasArg(PREF_APRS_SHOW_BATTERY)); + preferences.putBool(PREF_APRS_SHOW_ALTITUDE, server.hasArg(PREF_APRS_SHOW_ALTITUDE)); + preferences.putBool(PREF_APRS_FIXED_BEACON_PRESET, server.hasArg(PREF_APRS_FIXED_BEACON_PRESET)); + + + server.sendHeader("Location", "/"); + server.send(302,"text/html", ""); + +} + +[[noreturn]] void taskWebServer(void *parameter) { + auto *webServerCfg = (tWebServerCfg*)parameter; + apSSID = webServerCfg->callsign + " AP"; + + server.on("/", handle_Index); + server.on("/favicon.ico", handle_NotFound); + server.on("/style.css", handle_Style); + server.on("/js.js", handle_Js); + server.on("/scan_wifi", handle_ScanWifi); + server.on("/save_wifi_cfg", handle_SaveWifiCfg); + server.on("/reboot", handle_Reboot); + server.on("/cfg", handle_Cfg); + server.on("/save_aprs_cfg", handle_SaveAPRSCfg); + server.on("/restore", handle_Restore); + server.onNotFound(handle_NotFound); + + String wifi_password = preferences.getString("wifi_password"); + String wifi_ssid = preferences.getString("wifi_ssid"); + if (!wifi_password.length() || !wifi_ssid.length()){ + WiFi.softAP(apSSID.c_str(), apPassword.c_str()); + } else { + WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str()); + Serial.println("Connecting to" + wifi_ssid); + while (WiFi.status() != WL_CONNECTED) { + Serial.println("Not connected"); + vTaskDelay(500/portTICK_PERIOD_MS); + } + } + + server.begin(); + if (MDNS.begin(webServerCfg->callsign.c_str())) { + MDNS.addService("http", "tcp", 80); + } + + while (true){ + server.handleClient(); + vTaskDelay(5/portTICK_PERIOD_MS); + } +} \ No newline at end of file diff --git a/tools/buildscript_versioning.py b/tools/buildscript_versioning.py new file mode 100644 index 0000000..72b722f --- /dev/null +++ b/tools/buildscript_versioning.py @@ -0,0 +1,39 @@ +FILENAME_BUILDNO = '.pio/versioning' +FILENAME_VERSION_H = 'include/version.h' +version = 'v0.1.' + +import datetime + +build_no = 0 +try: + with open(FILENAME_BUILDNO) as f: + build_no = int(f.readline()) + 1 +except: + print('Starting build number from 1..') + build_no = 1 +with open(FILENAME_BUILDNO, 'w+') as f: + f.write(str(build_no)) + print('Build number: {}'.format(build_no)) + +version_string = "{} - {}".format(version+str(build_no), datetime.datetime.now()) +hf = """ +#ifndef BUILD_NUMBER + #define BUILD_NUMBER "{}" +#endif +#ifndef VERSION + #define VERSION "{}" +#endif +#ifndef VERSION_SHORT + #define VERSION_SHORT "{}" +#endif +""".format(build_no, version_string, version+str(build_no)) +with open(FILENAME_VERSION_H, 'w+') as f: + f.write(hf) + +with open("data_embed/index.html", "r") as f: + index_html_content = f.read() + +index_html_content = index_html_content.replace('', version_string) + +with open("data_embed/index.html.out", "w") as f: + f.write(index_html_content) diff --git a/tools/compress_assets.py b/tools/compress_assets.py new file mode 100644 index 0000000..60a395d --- /dev/null +++ b/tools/compress_assets.py @@ -0,0 +1,13 @@ +import gzip +assets_list = { + 'data_embed/index.html.out': 'data_embed/index.html.out', + 'data_embed/js.js': 'data_embed/js.js.out', + 'data_embed/style.css': 'data_embed/style.css.out', +} + + +for src_file_name, out_file_name in assets_list.items(): + with open(src_file_name, 'rb') as f: + content = f.read() + with open(out_file_name, 'wb') as f: + f.write(gzip.compress(content, compresslevel=9)) From 316d8cb7116b1dd90a91d79d58ebc9556e6b83f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 19:34:42 +0100 Subject: [PATCH 02/18] NETWORK_TNC test --- include/taskTNC.h | 5 +++- include/taskWebServer.h | 10 ++++++- src/TTGO_T-Beam_LoRa_APRS_config.h | 1 + src/taskTNC.cpp | 44 ++++++++++++++++++++++++------ src/taskWebServer.cpp | 9 ++++++ 5 files changed, 58 insertions(+), 11 deletions(-) diff --git a/include/taskTNC.h b/include/taskTNC.h index 6099654..70b4546 100644 --- a/include/taskTNC.h +++ b/include/taskTNC.h @@ -6,8 +6,11 @@ #include "BluetoothSerial.h" extern BluetoothSerial SerialBT; #endif +#if defined(ENABLE_WIFI) + #include "taskWebServer.h" +#endif extern QueueHandle_t tncToSendQueue; extern QueueHandle_t tncReceivedQueue; -void taskTNC(void *parameter); +[[noreturn]] void taskTNC(void *parameter); diff --git a/include/taskWebServer.h b/include/taskWebServer.h index a904511..43a6092 100644 --- a/include/taskWebServer.h +++ b/include/taskWebServer.h @@ -5,9 +5,16 @@ #include #include +#ifndef TASK_WEBSERVER +#define TASK_WEBSERVER + + #define ENABLE_PREFERENCES extern Preferences preferences; +#ifdef KISS_PROTOCOL + extern WiFiServer tncServer; +#endif // MAX 15 chars for preferenece key!!! static const char *const PREF_APRS_CALLSIGN = "aprs_callsign"; static const char *const PREF_APRS_RELAY_PATH = "aprs_relay_path"; @@ -33,4 +40,5 @@ typedef struct { String callsign; } tWebServerCfg; -[[noreturn]] void taskWebServer(void *parameter); \ No newline at end of file +[[noreturn]] void taskWebServer(void *parameter); +#endif \ No newline at end of file diff --git a/src/TTGO_T-Beam_LoRa_APRS_config.h b/src/TTGO_T-Beam_LoRa_APRS_config.h index 1be7eaa..b12bac1 100644 --- a/src/TTGO_T-Beam_LoRa_APRS_config.h +++ b/src/TTGO_T-Beam_LoRa_APRS_config.h @@ -29,6 +29,7 @@ #define T_BEAM_V1_0 // if enabled t-beam v1.0 disabled t-beam V.0.7 //#define KISS_DEBUG #define ENABLE_WIFI +#define NETWORK_TNC_PORT 8001 #define MAX_TIME_TO_NEXT_TX 360000L // TRANSMIT INTERVAL set here MAXIMUM time in ms(!) for smart beaconing - minimum time is always 1 min = 60 secs = 60000L !!! #define FIX_BEACON_INTERVAL 1800000L // Fixed beacon interwal (when GPS is disabled and FIXED_BEACON_EN is enabled) 30min default diff --git a/src/taskTNC.cpp b/src/taskTNC.cpp index aef8ad4..a18bd0f 100644 --- a/src/taskTNC.cpp +++ b/src/taskTNC.cpp @@ -6,6 +6,7 @@ String inTNCData = ""; QueueHandle_t tncToSendQueue = nullptr; QueueHandle_t tncReceivedQueue = nullptr; +WiFiClient client; /** * Handle incoming TNC KISS data character @@ -23,6 +24,12 @@ void handleKISSData(char character) { SerialBT.print(inTNCData); } #endif + #ifdef ENABLE_WIFI + if (client.connected()){ + client.print(inTNCData); + client.flush(); + } + #endif #endif auto *buffer = new String(); buffer->concat(TNC2DataFrame); @@ -34,31 +41,50 @@ void handleKISSData(char character) { } -void taskTNC(void *parameter) { +[[noreturn]] void taskTNC(void *parameter) { tncToSendQueue = xQueueCreate(4,sizeof(String *)); tncReceivedQueue = xQueueCreate(4,sizeof(String *)); String *loraReceivedFrameString = nullptr; - + client = tncServer.available(); while (true) { while (Serial.available() > 0) { char character = Serial.read(); handleKISSData(character); } #ifdef ENABLE_BLUETOOTH - if (SerialBT.hasClient()) { - while (SerialBT.available() > 0) { - char character = SerialBT.read(); - handleKISSData(character); + if (SerialBT.hasClient()) { + while (SerialBT.available() > 0) { + char character = SerialBT.read(); + handleKISSData(character); + } + } + #endif + #ifdef ENABLE_WIFI + if (!client.connected()){ + client = tncServer.available(); + } + if (client.connected()){ + while (client.available() > 0) { + char character = client.read(); + handleKISSData(character); + } } - } #endif if (xQueueReceive(tncReceivedQueue, &loraReceivedFrameString, (1 / portTICK_PERIOD_MS)) == pdPASS) { - Serial.print(encode_kiss(*loraReceivedFrameString)); + const String &kissEncoded = encode_kiss(*loraReceivedFrameString); + Serial.print(kissEncoded); #ifdef ENABLE_BLUETOOTH if (SerialBT.hasClient()){ - SerialBT.print(encode_kiss(*loraReceivedFrameString)); + SerialBT.print(kissEncoded); } #endif + #ifdef ENABLE_WIFI + if (client.connected()){ + client.print(kissEncoded); + client.flush(); + } + #endif + delete loraReceivedFrameString; } vTaskDelay(50 / portTICK_PERIOD_MS); diff --git a/src/taskWebServer.cpp b/src/taskWebServer.cpp index d302ffa..8eb3959 100644 --- a/src/taskWebServer.cpp +++ b/src/taskWebServer.cpp @@ -14,6 +14,9 @@ String apSSID = ""; String apPassword = "xxxxxxxxxx"; WebServer server(80); Preferences preferences; +#ifdef KISS_PROTOCOL + WiFiServer tncServer(NETWORK_TNC_PORT); +#endif void sendCacheHeader() { server.sendHeader("Cache-Control", "max-age=3600"); } void sendGzipHeader() { server.sendHeader("Content-Encoding", "gzip"); } @@ -181,8 +184,14 @@ void handle_SaveAPRSCfg() { } server.begin(); + #ifdef KISS_PROTOCOL + tncServer.begin(); + #endif if (MDNS.begin(webServerCfg->callsign.c_str())) { MDNS.addService("http", "tcp", 80); + #ifdef KISS_PROTOCOL + MDNS.addService("kiss-tnc", "tcp", NETWORK_TNC_PORT); + #endif } while (true){ From 713fe63b12bfe525040b77e3f7c76f382a804d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 20:37:05 +0100 Subject: [PATCH 03/18] Handle multiple TNC network clients --- src/taskTNC.cpp | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/src/taskTNC.cpp b/src/taskTNC.cpp index a18bd0f..2b51609 100644 --- a/src/taskTNC.cpp +++ b/src/taskTNC.cpp @@ -1,3 +1,4 @@ +#include #include "taskTNC.h" #ifdef ENABLE_BLUETOOTH @@ -6,7 +7,6 @@ String inTNCData = ""; QueueHandle_t tncToSendQueue = nullptr; QueueHandle_t tncReceivedQueue = nullptr; -WiFiClient client; /** * Handle incoming TNC KISS data character @@ -40,12 +40,31 @@ void handleKISSData(char character) { } } +#ifdef ENABLE_WIFI +typedef void (*f_connectedClientCallback_t) (WiFiClient *, const String *); + +void iterateWifiClients(std::list clients, f_connectedClientCallback_t callback, const String *data){ + auto clientsIterator = clients.begin(); + while (clientsIterator != clients.end()){ + if ((*clientsIterator)->connected()){ + callback(*clientsIterator, data); + clientsIterator++; + } else { + clientsIterator = clients.erase(clientsIterator); + } + } +} +#endif + [[noreturn]] void taskTNC(void *parameter) { tncToSendQueue = xQueueCreate(4,sizeof(String *)); tncReceivedQueue = xQueueCreate(4,sizeof(String *)); String *loraReceivedFrameString = nullptr; - client = tncServer.available(); + #ifdef ENABLE_WIFI + std::list clients; + #endif + while (true) { while (Serial.available() > 0) { char character = Serial.read(); @@ -60,15 +79,17 @@ void handleKISSData(char character) { } #endif #ifdef ENABLE_WIFI - if (!client.connected()){ - client = tncServer.available(); + WiFiClient new_client = tncServer.available(); + if (new_client.connected()){ + clients.push_back(new WiFiClient(new_client)); } - if (client.connected()){ - while (client.available() > 0) { - char character = client.read(); + iterateWifiClients(clients, [](WiFiClient * client, const String * unused){ + while (client->available() > 0) { + char character = client->read(); handleKISSData(character); } - } + }, nullptr); + #endif if (xQueueReceive(tncReceivedQueue, &loraReceivedFrameString, (1 / portTICK_PERIOD_MS)) == pdPASS) { const String &kissEncoded = encode_kiss(*loraReceivedFrameString); @@ -79,10 +100,12 @@ void handleKISSData(char character) { } #endif #ifdef ENABLE_WIFI - if (client.connected()){ - client.print(kissEncoded); - client.flush(); - } + iterateWifiClients(clients, [](WiFiClient *client, const String *data){ + if (client->connected()){ + client->print(*data); + client->flush(); + } + }, &kissEncoded); #endif delete loraReceivedFrameString; From 70b16efa4ad3ecd0559195e0bf1772b9b09df02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 20:45:40 +0100 Subject: [PATCH 04/18] Mem info in json response --- src/taskWebServer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/taskWebServer.cpp b/src/taskWebServer.cpp index 8eb3959..f349f0f 100644 --- a/src/taskWebServer.cpp +++ b/src/taskWebServer.cpp @@ -36,6 +36,9 @@ String jsonLineFromPreferenceBool(const char *preferenceName, bool last=false){ String jsonLineFromPreferenceInt(const char *preferenceName, bool last=false){ return String("\"") + preferenceName + "\":" + (preferences.getInt(preferenceName)) + (last ? + R"()" : + R"(,)"); } +String jsonLineFromString(const char *name, const char *value, bool last=false){ + return String("\"") + name + "\":" + jsonEscape(value) + (last ? + R"()" : + R"(,)"); +} void handle_NotFound(){ sendCacheHeader(); @@ -114,7 +117,11 @@ void handle_Cfg() { jsonData += jsonLineFromPreferenceInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET); jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_BATTERY); jsonData += jsonLineFromPreferenceBool(PREF_APRS_FIXED_BEACON_PRESET); - jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_ALTITUDE, true); + jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_ALTITUDE); + jsonData += jsonLineFromString("FreeHeap", String(ESP.getFreeHeap()).c_str()); + jsonData += jsonLineFromString("HeapSize", String(ESP.getHeapSize()).c_str()); + jsonData += jsonLineFromString("FreeSketchSpace", String(ESP.getFreeSketchSpace()).c_str(), true); + jsonData += "}"; server.send(200,"application/json", jsonData); } From 3091f535abeec7a14398c172e2a96c3c590351ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 21:22:45 +0100 Subject: [PATCH 05/18] DNS-SD instance name --- src/taskWebServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/taskWebServer.cpp b/src/taskWebServer.cpp index f349f0f..1a45dea 100644 --- a/src/taskWebServer.cpp +++ b/src/taskWebServer.cpp @@ -183,7 +183,7 @@ void handle_SaveAPRSCfg() { WiFi.softAP(apSSID.c_str(), apPassword.c_str()); } else { WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str()); - Serial.println("Connecting to" + wifi_ssid); + Serial.println("Connecting to " + wifi_ssid); while (WiFi.status() != WL_CONNECTED) { Serial.println("Not connected"); vTaskDelay(500/portTICK_PERIOD_MS); @@ -195,6 +195,7 @@ void handle_SaveAPRSCfg() { tncServer.begin(); #endif if (MDNS.begin(webServerCfg->callsign.c_str())) { + MDNS.setInstanceName(webServerCfg->callsign + " TTGO LoRa APRS TNC " + TXFREQ + "MHz"); MDNS.addService("http", "tcp", 80); #ifdef KISS_PROTOCOL MDNS.addService("kiss-tnc", "tcp", NETWORK_TNC_PORT); From 13964e152bf5f1e0a9a71e4b52210a20c2e5a50c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 23:01:15 +0100 Subject: [PATCH 06/18] Fix LOCAL_KISS_ECHO for WiFi clients --- src/taskTNC.cpp | 53 +++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/taskTNC.cpp b/src/taskTNC.cpp index 2b51609..c1251eb 100644 --- a/src/taskTNC.cpp +++ b/src/taskTNC.cpp @@ -7,6 +7,24 @@ String inTNCData = ""; QueueHandle_t tncToSendQueue = nullptr; QueueHandle_t tncReceivedQueue = nullptr; +#ifdef ENABLE_WIFI + std::list clientsList; + + typedef void (*f_connectedClientCallback_t) (WiFiClient *, const String *); + + void iterateWifiClients(std::list clients, f_connectedClientCallback_t callback, const String *data){ + auto clientsIterator = clients.begin(); + while (clientsIterator != clients.end()){ + if ((*clientsIterator)->connected()){ + callback(*clientsIterator, data); + clientsIterator++; + } else { + clientsIterator = clients.erase(clientsIterator); + } + } + } +#endif + /** * Handle incoming TNC KISS data character @@ -25,10 +43,12 @@ void handleKISSData(char character) { } #endif #ifdef ENABLE_WIFI - if (client.connected()){ - client.print(inTNCData); - client.flush(); - } + iterateWifiClients(clientsList, [](WiFiClient *client, const String *data){ + if (client->connected()){ + client->print(*data); + client->flush(); + } + }, &inTNCData); #endif #endif auto *buffer = new String(); @@ -40,30 +60,11 @@ void handleKISSData(char character) { } } -#ifdef ENABLE_WIFI -typedef void (*f_connectedClientCallback_t) (WiFiClient *, const String *); - -void iterateWifiClients(std::list clients, f_connectedClientCallback_t callback, const String *data){ - auto clientsIterator = clients.begin(); - while (clientsIterator != clients.end()){ - if ((*clientsIterator)->connected()){ - callback(*clientsIterator, data); - clientsIterator++; - } else { - clientsIterator = clients.erase(clientsIterator); - } - } -} -#endif - [[noreturn]] void taskTNC(void *parameter) { tncToSendQueue = xQueueCreate(4,sizeof(String *)); tncReceivedQueue = xQueueCreate(4,sizeof(String *)); String *loraReceivedFrameString = nullptr; - #ifdef ENABLE_WIFI - std::list clients; - #endif while (true) { while (Serial.available() > 0) { @@ -81,9 +82,9 @@ void iterateWifiClients(std::list clients, f_connectedClientCallba #ifdef ENABLE_WIFI WiFiClient new_client = tncServer.available(); if (new_client.connected()){ - clients.push_back(new WiFiClient(new_client)); + clientsList.push_back(new WiFiClient(new_client)); } - iterateWifiClients(clients, [](WiFiClient * client, const String * unused){ + iterateWifiClients(clientsList, [](WiFiClient * client, const String * unused){ while (client->available() > 0) { char character = client->read(); handleKISSData(character); @@ -100,7 +101,7 @@ void iterateWifiClients(std::list clients, f_connectedClientCallba } #endif #ifdef ENABLE_WIFI - iterateWifiClients(clients, [](WiFiClient *client, const String *data){ + iterateWifiClients(clientsList, [](WiFiClient *client, const String *data){ if (client->connected()){ client->print(*data); client->flush(); From 3625b61697f23385caa0417775fa9a9e96de853d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Thu, 18 Feb 2021 23:11:56 +0100 Subject: [PATCH 07/18] Fix: Fixed beacon option was not saved --- data_embed/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_embed/index.html b/data_embed/index.html index bbcbbb6..ecbdb9c 100644 --- a/data_embed/index.html +++ b/data_embed/index.html @@ -82,7 +82,7 @@
- +
From 1e0fe1071ebfbb4f86e61d3ffdb6bce8915114b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Fri, 19 Feb 2021 01:27:14 +0100 Subject: [PATCH 08/18] Change in TNC Network clients handling --- src/TTGO_T-Beam_LoRa_APRS.ino | 4 +- src/TTGO_T-Beam_LoRa_APRS_config.h | 2 + src/taskTNC.cpp | 63 +++++++++++++++++++++++------- 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index f63569a..21aa45e 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -498,7 +498,7 @@ void setup(){ } writedisplaytext("LoRa-APRS","","Init:","RF95 OK!","","",250); writedisplaytext(" "+Tcall,"","Init:","Waiting for GPS","","",250); - xTaskCreate(taskGPS, "taskGPS", 10000, nullptr, 1, nullptr); + xTaskCreate(taskGPS, "taskGPS", 5000, nullptr, 1, nullptr); writedisplaytext(" "+Tcall,"","Init:","GPS Task Created!","","",250); #ifndef T_BEAM_V1_0 adc1_config_width(ADC_WIDTH_BIT_12); @@ -523,7 +523,7 @@ void setup(){ #endif #ifdef ENABLE_WIFI webServerCfg = {.callsign = Tcall}; - xTaskCreate(taskWebServer, "taskWebServer", 50000, (void*)(&webServerCfg), 1, nullptr); + xTaskCreate(taskWebServer, "taskWebServer", 40000, (void*)(&webServerCfg), 1, nullptr); writedisplaytext("LoRa-APRS","","Init:","WiFi task started"," =:-) ","",250); #endif diff --git a/src/TTGO_T-Beam_LoRa_APRS_config.h b/src/TTGO_T-Beam_LoRa_APRS_config.h index 25f5345..2edc908 100644 --- a/src/TTGO_T-Beam_LoRa_APRS_config.h +++ b/src/TTGO_T-Beam_LoRa_APRS_config.h @@ -29,6 +29,8 @@ //#define KISS_DEBUG #define ENABLE_WIFI #define NETWORK_TNC_PORT 8001 +//#define ENABLE_WIFI_CLIENT_DEBUG + #define MAX_TIME_TO_NEXT_TX 360000L // TRANSMIT INTERVAL set here MAXIMUM time in ms(!) for smart beaconing - minimum time is always 1 min = 60 secs = 60000L !!! #define FIX_BEACON_INTERVAL 1800000L // Fixed beacon interwal (when GPS is disabled and FIXED_BEACON_EN is enabled) 30min default diff --git a/src/taskTNC.cpp b/src/taskTNC.cpp index c1251eb..5e16ce6 100644 --- a/src/taskTNC.cpp +++ b/src/taskTNC.cpp @@ -1,6 +1,6 @@ -#include #include "taskTNC.h" + #ifdef ENABLE_BLUETOOTH BluetoothSerial SerialBT; #endif @@ -8,18 +8,24 @@ String inTNCData = ""; QueueHandle_t tncToSendQueue = nullptr; QueueHandle_t tncReceivedQueue = nullptr; #ifdef ENABLE_WIFI - std::list clientsList; + #define MAX_WIFI_CLIENTS 6 + WiFiClient * clients[MAX_WIFI_CLIENTS]; typedef void (*f_connectedClientCallback_t) (WiFiClient *, const String *); - void iterateWifiClients(std::list clients, f_connectedClientCallback_t callback, const String *data){ - auto clientsIterator = clients.begin(); - while (clientsIterator != clients.end()){ - if ((*clientsIterator)->connected()){ - callback(*clientsIterator, data); - clientsIterator++; - } else { - clientsIterator = clients.erase(clientsIterator); + void iterateWifiClients(f_connectedClientCallback_t callback, const String *data){ + for (int i=0; iconnected()) { + callback(client, data); + } else { + #ifdef ENABLE_WIFI_CLIENT_DEBUG + Serial.println(String("Disconnected client ") + client->remoteIP().toString() + ":" + client->remotePort()); + #endif + delete client; + clients[i] = nullptr; + } } } } @@ -43,7 +49,7 @@ void handleKISSData(char character) { } #endif #ifdef ENABLE_WIFI - iterateWifiClients(clientsList, [](WiFiClient *client, const String *data){ + iterateWifiClients([](WiFiClient *client, const String *data){ if (client->connected()){ client->print(*data); client->flush(); @@ -82,9 +88,38 @@ void handleKISSData(char character) { #ifdef ENABLE_WIFI WiFiClient new_client = tncServer.available(); if (new_client.connected()){ - clientsList.push_back(new WiFiClient(new_client)); + bool new_client_handled = false; + for (int i=0; i < MAX_WIFI_CLIENTS; i++) { + auto client = clients[i]; + if (client == nullptr) { + client = new WiFiClient(new_client); + clients[i] = client; + new_client_handled = true; + #ifdef ENABLE_WIFI_CLIENT_DEBUG + Serial.println(String("New client #") +String(i) + ": " + client->remoteIP().toString() + ":" + client->remotePort()); + #endif + break; + } + } + #ifdef ENABLE_WIFI_CLIENT_DEBUG + for (int i = 0; i < MAX_WIFI_CLIENTS; ++i) { + auto client = clients[i]; + + if (client != nullptr){ + Serial.println(String("Client #") +String(i) + ": " + client->remoteIP().toString() + ":" + client->remotePort()); + } + } + #endif + + + if (!new_client_handled){ + #ifdef ENABLE_WIFI_CLIENT_DEBUG + Serial.println(String("Refusing client ")); + #endif + new_client.stop(); + } } - iterateWifiClients(clientsList, [](WiFiClient * client, const String * unused){ + iterateWifiClients([](WiFiClient * client, const String * unused){ while (client->available() > 0) { char character = client->read(); handleKISSData(character); @@ -101,7 +136,7 @@ void handleKISSData(char character) { } #endif #ifdef ENABLE_WIFI - iterateWifiClients(clientsList, [](WiFiClient *client, const String *data){ + iterateWifiClients([](WiFiClient *client, const String *data){ if (client->connected()){ client->print(*data); client->flush(); From 784937381f7a59ae7f649ce96d8f802c35e63e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Fri, 19 Feb 2021 01:56:43 +0100 Subject: [PATCH 09/18] Separate TNC input buffers for different connections --- src/taskTNC.cpp | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/taskTNC.cpp b/src/taskTNC.cpp index 5e16ce6..8c499c4 100644 --- a/src/taskTNC.cpp +++ b/src/taskTNC.cpp @@ -4,21 +4,20 @@ #ifdef ENABLE_BLUETOOTH BluetoothSerial SerialBT; #endif -String inTNCData = ""; -QueueHandle_t tncToSendQueue = nullptr; + QueueHandle_t tncReceivedQueue = nullptr; #ifdef ENABLE_WIFI #define MAX_WIFI_CLIENTS 6 WiFiClient * clients[MAX_WIFI_CLIENTS]; - typedef void (*f_connectedClientCallback_t) (WiFiClient *, const String *); + typedef void (*f_connectedClientCallback_t) (WiFiClient *, int, const String *); void iterateWifiClients(f_connectedClientCallback_t callback, const String *data){ for (int i=0; iconnected()) { - callback(client, data); + callback(client, i, data); } else { #ifdef ENABLE_WIFI_CLIENT_DEBUG Serial.println(String("Disconnected client ") + client->remoteIP().toString() + ":" + client->remotePort()); @@ -30,16 +29,30 @@ QueueHandle_t tncReceivedQueue = nullptr; } } #endif +#ifdef ENABLE_WIFI + #define IN_TNC_BUFFERS (2+MAX_WIFI_CLIENTS) +#else + #define IN_TNC_BUFFERS 2 +#endif + +String inTNCDataBuffers[IN_TNC_BUFFERS]; + +QueueHandle_t tncToSendQueue = nullptr; /** * Handle incoming TNC KISS data character * @param character */ -void handleKISSData(char character) { - inTNCData.concat(character); - if (character == (char) FEND && inTNCData.length() > 3) { - const String &TNC2DataFrame = decode_kiss(inTNCData); +void handleKISSData(char character, int bufferIndex) { + String *inTNCData = &inTNCDataBuffers[bufferIndex]; + if (inTNCData->length() == 0 && character != (char) FEND){ + // kiss frame begins with C0 + return; + } + inTNCData->concat(character); + if (character == (char) FEND && inTNCData->length() > 3) { + const String &TNC2DataFrame = decode_kiss(*inTNCData); #ifdef LOCAL_KISS_ECHO Serial.print(inTNCData); @@ -62,7 +75,11 @@ void handleKISSData(char character) { if (xQueueSend(tncToSendQueue, &buffer, (1000 / portTICK_PERIOD_MS)) != pdPASS){ delete buffer; } - inTNCData = ""; + inTNCData->clear(); + } + if (inTNCData->length() > 255){ + // just in case of garbage input reset data + inTNCData->clear(); } } @@ -75,13 +92,13 @@ void handleKISSData(char character) { while (true) { while (Serial.available() > 0) { char character = Serial.read(); - handleKISSData(character); + handleKISSData(character, 0); } #ifdef ENABLE_BLUETOOTH if (SerialBT.hasClient()) { while (SerialBT.available() > 0) { char character = SerialBT.read(); - handleKISSData(character); + handleKISSData(character, 1); } } #endif @@ -119,10 +136,10 @@ void handleKISSData(char character) { new_client.stop(); } } - iterateWifiClients([](WiFiClient * client, const String * unused){ + iterateWifiClients([](WiFiClient * client, int clientIdx, const String * unused){ while (client->available() > 0) { char character = client->read(); - handleKISSData(character); + handleKISSData(character, 2+clientIdx); } }, nullptr); @@ -136,7 +153,7 @@ void handleKISSData(char character) { } #endif #ifdef ENABLE_WIFI - iterateWifiClients([](WiFiClient *client, const String *data){ + iterateWifiClients([](WiFiClient *client, int clientIdx, const String *data){ if (client->connected()){ client->print(*data); client->flush(); From 5c56456e3f7597da32ca76d1f269b8de38d04f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Fri, 19 Feb 2021 01:57:56 +0100 Subject: [PATCH 10/18] Fix in reading fixed position from preferences --- src/TTGO_T-Beam_LoRa_APRS.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index 21aa45e..5f96386 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -427,7 +427,7 @@ void setup(){ preferences.putBool(PREF_APRS_LATITUDE_PRESET_INIT, true); preferences.putString(PREF_APRS_LATITUDE_PRESET, LATIDUDE_PRESET); } - aprsLatPreset = preferences.getString(LATIDUDE_PRESET); + aprsLatPreset = preferences.getString(PREF_APRS_LATITUDE_PRESET); if (!preferences.getBool(PREF_APRS_LONGITUDE_PRESET_INIT)){ preferences.putBool(PREF_APRS_LONGITUDE_PRESET_INIT, true); From 4cb94db0bd8062fb657003f8e6abf622ee78409d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Mon, 22 Feb 2021 21:30:27 +0100 Subject: [PATCH 11/18] Factory reset at startup --- src/TTGO_T-Beam_LoRa_APRS.ino | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index 5f96386..0a8f86f 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -386,6 +386,11 @@ void setup(){ #endif #ifdef ENABLE_PREFERENCES + int clear_preferences = 0; + if(digitalRead(BUTTON)==LOW){ + clear_preferences = 1; + } + preferences.begin("cfg", false); aprsSymbolTable = preferences.getString(PREF_APRS_SYMBOL_TABLE); if (aprsSymbolTable.isEmpty()){ @@ -446,7 +451,14 @@ void setup(){ preferences.putInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET, fix_beacon_interval/1000); } fix_beacon_interval = preferences.getInt(PREF_APRS_FIXED_BEACON_PRESET) * 1000; + if (clear_preferences){ + delay(1000); + if(digitalRead(BUTTON)==LOW){ + clear_preferences = 2; + preferences.clear(); + } + } #endif for (int i=0;i Date: Mon, 22 Feb 2021 21:32:06 +0100 Subject: [PATCH 12/18] Factory reset at startup --- src/TTGO_T-Beam_LoRa_APRS.ino | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index 0a8f86f..94fb913 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -455,7 +455,6 @@ void setup(){ delay(1000); if(digitalRead(BUTTON)==LOW){ clear_preferences = 2; - preferences.clear(); } } @@ -491,7 +490,14 @@ void setup(){ #ifdef ENABLE_PREFERENCES if (clear_preferences == 2){ writedisplaytext("LoRa-APRS","","","Factory reset!!","","",0); - delay(3000); + delay(1000); + if(digitalRead(BUTTON)==LOW){ + clear_preferences = 3; + preferences.clear(); + writedisplaytext("LoRa-APRS","","Factory reset","OK","","",0); + delay(2000); + + } ESP.restart(); } #endif From 4e8899330ec28e3138a057c0050f9ba0ff2bca48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Mon, 22 Feb 2021 21:50:04 +0100 Subject: [PATCH 13/18] Factory reset at startup --- src/TTGO_T-Beam_LoRa_APRS.ino | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index 94fb913..9f1661e 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -489,16 +489,19 @@ void setup(){ } #ifdef ENABLE_PREFERENCES if (clear_preferences == 2){ - writedisplaytext("LoRa-APRS","","","Factory reset!!","","",0); + writedisplaytext("LoRa-APRS","","","Factory reset","","",0); delay(1000); if(digitalRead(BUTTON)==LOW){ clear_preferences = 3; preferences.clear(); - writedisplaytext("LoRa-APRS","","Factory reset","OK","","",0); + preferences.end(); + writedisplaytext("LoRa-APRS","","Factory reset","Done!","","",0); + delay(2000); + ESP.restart(); + } else { + writedisplaytext("LoRa-APRS","","Factory reset","Cancel","","",0); delay(2000); - } - ESP.restart(); } #endif writedisplaytext("LoRa-APRS","","Init:","Display OK!","","",1000); From 6bcaadb31d89c582d73710c47750c56755576ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Mon, 22 Feb 2021 22:20:43 +0100 Subject: [PATCH 14/18] Show wifi status in serial message --- src/taskWebServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/taskWebServer.cpp b/src/taskWebServer.cpp index 1a45dea..c2667c2 100644 --- a/src/taskWebServer.cpp +++ b/src/taskWebServer.cpp @@ -185,7 +185,8 @@ void handle_SaveAPRSCfg() { WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str()); Serial.println("Connecting to " + wifi_ssid); while (WiFi.status() != WL_CONNECTED) { - Serial.println("Not connected"); + Serial.print("Not connected: "); + Serial.println((int)WiFi.status()); vTaskDelay(500/portTICK_PERIOD_MS); } } From 0aa6b3e32caf0982ffd71d3020e5e72f78b4a938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Tue, 23 Feb 2021 16:49:22 +0100 Subject: [PATCH 15/18] Fix in fixed interval time --- src/TTGO_T-Beam_LoRa_APRS.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TTGO_T-Beam_LoRa_APRS.ino b/src/TTGO_T-Beam_LoRa_APRS.ino index 9f1661e..23d530f 100644 --- a/src/TTGO_T-Beam_LoRa_APRS.ino +++ b/src/TTGO_T-Beam_LoRa_APRS.ino @@ -450,7 +450,7 @@ void setup(){ preferences.putBool(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET_INIT, true); preferences.putInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET, fix_beacon_interval/1000); } - fix_beacon_interval = preferences.getInt(PREF_APRS_FIXED_BEACON_PRESET) * 1000; + fix_beacon_interval = preferences.getInt(PREF_APRS_FIXED_BEACON_INTERVAL_PRESET) * 1000; if (clear_preferences){ delay(1000); if(digitalRead(BUTTON)==LOW){ From 77ecdfe942e133f98210912513247cb92a026c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Tue, 23 Feb 2021 17:00:33 +0100 Subject: [PATCH 16/18] Move T_BEAM_V1_0 option to platformio.ini --- platformio.ini | 17 +++++------------ src/TTGO_T-Beam_LoRa_APRS_config.h | 3 ++- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/platformio.ini b/platformio.ini index 2f3e46d..d2e910e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,6 +9,9 @@ ; https://docs.platformio.org/page/projectconf.html [env] +platform = espressif32 +framework = arduino + monitor_speed = 115200 build_flags = -Wl,--gc-sections,--relax board_build.partitions = no_ota.csv @@ -22,27 +25,17 @@ extra_scripts = lib_deps = RadioHead TinyGPSPlus - #DHT sensor library for ESPx Adafruit SSD1306 Adafruit GFX Library Adafruit Unified Sensor AXP202X_Library - OneWire - #DallasTemperature - #adafruit/Adafruit BME280 Library@^2.1.2 - [env:ttgo-t-beam] -platform = espressif32 board = ttgo-t-beam -framework = arduino +build_flags = ${env.build_flags} -DT_BEAM_V1_0 [env:ttgo-lora32-v2] -platform = espressif32 board = ttgo-lora32-v1 -framework = arduino [env:ttgo-lora32-v1] -platform = espressif32 -board = ttgo-lora32-v1 -framework = arduino \ No newline at end of file +board = ttgo-lora32-v1 \ No newline at end of file diff --git a/src/TTGO_T-Beam_LoRa_APRS_config.h b/src/TTGO_T-Beam_LoRa_APRS_config.h index 2edc908..1ec51c2 100644 --- a/src/TTGO_T-Beam_LoRa_APRS_config.h +++ b/src/TTGO_T-Beam_LoRa_APRS_config.h @@ -25,7 +25,8 @@ //#define BLUETOOTH_PIN "0000" //#define ENABLE_TNC_SELF_TELEMETRY //#define LOCAL_KISS_ECHO // echoing KISS frame back -#define T_BEAM_V1_0 // if enabled t-beam v1.0 disabled t-beam V.0.7 +//#define T_BEAM_V1_0 // if enabled t-beam v1.0 disabled t-beam V.0.7 + // AUTOMATICALLY SET BY platformio.ini env! //#define KISS_DEBUG #define ENABLE_WIFI #define NETWORK_TNC_PORT 8001 From 7cea5e7fb8f0268d676e09f3fbfa4d06713c876a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Tue, 23 Feb 2021 17:03:33 +0100 Subject: [PATCH 17/18] Target for ttgo-t-beam v0.7 --- platformio.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platformio.ini b/platformio.ini index d2e910e..68d9c36 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,6 +34,9 @@ lib_deps = board = ttgo-t-beam build_flags = ${env.build_flags} -DT_BEAM_V1_0 +[env:ttgo-t-beam_v0.7] +board = ttgo-t-beam + [env:ttgo-lora32-v2] board = ttgo-lora32-v1 From 43001b85cdc2c9629ae391ca89452994f22fcdba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nidecki?= Date: Wed, 24 Feb 2021 21:40:43 +0100 Subject: [PATCH 18/18] Target for ttgo-t-beam v0.7 --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index e372b78..673298d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,7 +34,7 @@ lib_deps = board = ttgo-t-beam build_flags = ${env.build_flags} -DT_BEAM_V1_0 -[env:ttgo-t-beam_v0.7] +[env:ttgo-t-beam-v0.7] board = ttgo-t-beam build_flags = ${env.build_flags} -DT_BEAM_V0_7