Merge branch 'master' of https://github.com/SQ9MDD/TTGO-T-Beam-LoRa-APRS into master_sq9mdd

This commit is contained in:
Łukasz Nidecki 2021-03-22 18:35:01 +01:00
commit 725794ac23
18 changed files with 465 additions and 147 deletions

View File

@ -20,24 +20,22 @@
<article>
<form action="/save_wifi_cfg" method="post">
<div class="grid-container quarters">
<div>
<div id="wifi_list">
</div>
<div id="wifi_list">
<label for="wifi_ssid">Network</label>
<input type="button" value="Scan WiFi" id="scan_wifi_btn" onclick="scanWifi();">
</div>
<div>
<label for="wifi_ssid">SSID</label>
<input class="u-full-width" type="text" name="wifi_ssid" placeholder="Your Wifi SSID"
id="wifi_ssid">
<input class="u-full-width" type="text" name="wifi_ssid" placeholder="Your Wifi SSID" id="wifi_ssid">
</div>
<div>
<label for="wifi_password">Password</label>
<input class="u-full-width" type="password" name="wifi_password" id="wifi_password">
</div>
<div>
<input class="button-primary" type="submit" value="Save">
</div>
</div>
<div class="grid-container full">
<input class="button-primary" type="submit" value="Save">
</div>
</form>
</article>
</section>
@ -50,64 +48,117 @@
<div class="grid-container quarters">
<div>
<label for="aprs_callsign">Callsign and SSID</label>
<input class="u-full-width" type="text" minlength="3" name="aprs_callsign"
placeholder="NOCALL-1" id="aprs_callsign">
<input class="u-full-width" type="text" minlength="3" name="aprs_callsign" placeholder="NOCALL-1" id="aprs_callsign" title="your callsign with SSID">
</div>
<div>
<label for="aprs_relay_path">Relay Path</label>
<input class="u-full-width" type="text" minlength="0" name="aprs_relay_path"
id="aprs_relay_path">
<input class="u-full-width" type="text" minlength="0" name="aprs_relay_path" id="aprs_relay_path" title="APRS path, use the shortest as possible, ECHO or WIDE1-1">
</div>
<div>
<label for="aprs_s_table">Symbol Table</label>
<input class="u-full-width" type="text" minlength="1" maxlength="1" name="aprs_s_table"
id="aprs_s_table">
<input class="u-full-width" type="text" minlength="1" maxlength="1" name="aprs_s_table" id="aprs_s_table" title="use primary / or secondary table \ ">
</div>
<div>
<label for="aprs_symbol">Symbol</label>
<input class="u-full-width" type="text" minlength="1" maxlength="1" name="aprs_symbol"
id="aprs_symbol">
</div>
<div>
<label for="aprs_comment">Comment</label>
<input class="u-full-width" type="text" minlength="0" maxlength="64" name="aprs_comment"
id="aprs_comment">
</div>
<div>
<label for="aprs_batt">Show Battery</label>
<input name="aprs_batt" id="aprs_batt" type="checkbox" value="1">
<input class="u-full-width" type="text" minlength="1" maxlength="1" name="aprs_symbol" id="aprs_symbol" title="select an icon, for example: [ - jogger, Y - jacht, > - car, b - bike ">
</div>
<div>
<label for="aprs_alt">Show Altitude</label>
<input name="aprs_alt" id="aprs_alt" type="checkbox" value="1">
<input name="aprs_alt" id="aprs_alt" type="checkbox" value="1" title=" show altitude as frame part">
</div>
<div>
<label for="show_cmt">Show Comment</label>
<input name="show_cmt" id="show_cmt" type="checkbox" value="1" title=" show comment text">
</div>
<div>
<label for="aprs_comment">Comment</label>
<input class="u-full-width" type="text" minlength="0" maxlength="64" name="aprs_comment" id="aprs_comment" title=" personal comment">
</div>
<div>
<label for="aprs_batt">Show Battery</label>
<input name="aprs_batt" id="aprs_batt" type="checkbox" value="1" title=" show battery voltage after personal comment">
</div>
</div>
<div class="grid-container quarters">
<div>
<label for="aprs_fixed_beac">Fixed Beacon (when&nbsp;no&nbsp;GPS)</label>
<input name="aprs_fixed_beac" id="aprs_fixed_beac" type="checkbox" value="1">
<label for="aprs_fixed_beac">Fixed Beacon</label>
<input name="aprs_fixed_beac" id="aprs_fixed_beac" type="checkbox" value="1" title="enable fixed beacon when GPS is disabled or no fix">
</div>
<div>
<label for="aprs_fb_interv">Fixed Beacon Interval (s)</label>
<input name="aprs_fb_interv" id="aprs_fb_interv" type="number" min="120">
<input name="aprs_fb_interv" id="aprs_fb_interv" type="number" min="120" title="time between sending a beacon if Fixed Beacon option is selected ">
</div>
<div>
<label for="aprs_lat_p">Latitude Preset</label>
<input class="u-full-width" type="text" minlength="0" name="aprs_lat_p" id="aprs_lat_p">
<input class="u-full-width" type="text" minlength="0" name="aprs_lat_p" id="aprs_lat_p" title="latitude for fixed bicon, APRS format for example: 5215.0N">
</div>
<div>
<label for="aprs_lon_p">Longitude Preset</label>
<input class="u-full-width" type="text" minlength="0" name="aprs_lon_p" id="aprs_lon_p">
<input class="u-full-width" type="text" minlength="0" name="aprs_lon_p" id="aprs_lon_p" title="longtitude for fixed bicon, APRS format for example 02050.59E">
</div>
</div>
<div class="grid-container quarters">
<div>
<label for="gps_enabled">GPS enabled</label>
<input name="gps_enabled" id="gps_enabled" type="checkbox" value="1" title="enable or disable GPS">
</div>
</div>
<div class="grid-container full">
<div>
<input class="button-primary u-full-width" type="submit" value="Save">
<input class="button-primary u-full-width" type="submit" value="Save" title="save settings, remember reboot tracker after save">
</div>
</div>
</form>
</article>
</section>
<section>
<article>
<form action="/save_device_cfg" method="post">
<div class="grid-container full">
<h2 class="u-full-width">Device Settings</h2>
</div>
<div class="grid-container quarters">
<div>
<label for="oled_enabled">Display dimmer enabled</label>
<input name="oled_enabled" id="oled_enabled" type="checkbox" value="1" title="enable or disable oled dimmer">
</div>
<div>
<label for="bt_enabled">Bluetooth enabled</label>
<input name="bt_enabled" id="bt_enabled" type="checkbox" value="1" title="enable or disable bluetooth">
</div>
<div>
<label for="led_enable">LED signaling</label>
<input name="led_enable" id="led_enable" type="checkbox" value="1" title="enable or disable LED" DISABLED>
</div>
<div>
<label for="shutdown_act">Auto power off</label>
<input name="shutdown_act" id="shutdown_act" type="checkbox" value="1" title="activate auto shutdown after usb plug off">
</div>
</div>
<div class="grid-container quarters">
<div>
<label for="sh_rxtime">Display show RX time (s)</label>
<input name="sh_rxtime" id="sh_rxtime" type="number" min="1" max="45" title="show RX packet for seconds">
</div>
<div>
</div>
<div>
</div>
<div>
<label for="shutdown_dt">Auto power off delay (s)</label>
<input name="shutdown_dt" id="shutdown_dt" type="number" min="3" max="3600" title="auto shutdown delay in seconds">
</div>
</div>
<div class="grid-container full">
<div>
<input class="button-primary u-full-width" type="submit" value="Save" title="save settings, remember reboot tracker after save">
</div>
</div>
</form>
</article>
</section>
<section>
<div class="grid-container full">
<h2 class="u-full-width">Actions</h2>
@ -146,7 +197,7 @@
</section>
</div>
<footer>
<center><b>Contributors in order of appearance:</b> OE1ACM, OE3CJB, SQ9MDD, SQ5RWU, DJ1AN</center>
<center><b>Contributors in order of appearance:</b> OE1ACM, OE3CJB, SQ9MDD, SQ5RWU, DJ1AN, M0IGA, SQ5WPR</center>
<center><b>Latest stable version:</b> <a href=https://github.com/SQ9MDD/TTGO-T-Beam-LoRa-APRS>https://github.com/SQ9MDD/TTGO-T-Beam-LoRa-APRS</a></center>
<center><b>Licensed under:</b> CC BY-NC-SA</center>
<center><!--VERSION--></center>

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

View File

@ -38,6 +38,20 @@ 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";
static const char *const PREF_APRS_GPS_EN = "gps_enabled";
static const char *const PREF_APRS_GPS_EN_INIT = "gps_state_init";
static const char *const PREF_APRS_SHOW_CMT = "show_cmt";
static const char *const PREF_APRS_SHOW_CMT_INIT = "show_cmt_init";
static const char *const PREF_DEV_BT_EN = "bt_enabled";
static const char *const PREF_DEV_BT_EN_INIT = "bt_enabled_init";
static const char *const PREF_DEV_OL_EN = "oled_enabled";
static const char *const PREF_DEV_OL_EN_INIT = "ol_enabled_init";
static const char *const PREF_DEV_SHOW_RX_TIME = "sh_rxtime";
static const char *const PREF_DEV_SHOW_RX_TIME_INIT = "sh_rxtime_init";
static const char *const PREF_DEV_AUTO_SHUT = "shutdown_act";
static const char *const PREF_DEV_AUTO_SHUT_INIT = "shutdown_actini";
static const char *const PREF_DEV_AUTO_SHUT_PRESET = "shutdown_dt";
static const char *const PREF_DEV_AUTO_SHUT_PRESET_INIT = "shutdown_dtini";
typedef struct {
String callsign;

View File

@ -23,6 +23,8 @@ PROGMEM static const BG_RF95::ModemConfig MODEM_CONFIG_TABLE[] =
{ 0x48, 0x94, 0x00}, // Bw31_25Cr48Sf512
{ 0x78, 0xc4, 0x00}, // Bw125Cr48Sf4096
{ 0x72, 0xc7, 0x8}, // BG 125 cr45 sf12
{ 0x72, 0xb4, 0x00}, // Bw125Cr45Sf2048
{ 0x88, 0xc4, 0x00}, // Bw250Cr48Sf4096
};
BG_RF95::BG_RF95(uint8_t slaveSelectPin, uint8_t interruptPin, RHGenericSPI& spi)
@ -112,7 +114,7 @@ bool BG_RF95::init()
// setModemConfig(Bw125Cr48Sf4096); // slow and reliable?
setPreambleLength(8); // Default is 8
// An innocuous ISM frequency, same as RF22's
setFrequency(433.800);
setFrequency(433.850);
// Lowish power
setTxPower(20);

View File

@ -183,15 +183,15 @@
// BG_RF95_REG_1D_MODEM_CONFIG1 0x1d
#define BG_RF95_BW 0xc0
#define BG_RF95_BW_125KHZ 0x00
#define BG_RF95_BW_250KHZ 0x40
#define BG_RF95_BW_500KHZ 0x80
#define BG_RF95_BW_125KHZ 0x70
#define BG_RF95_BW_250KHZ 0x80
#define BG_RF95_BW_500KHZ 0x90
#define BG_RF95_BW_RESERVED 0xc0
#define BG_RF95_CODING_RATE 0x38
#define BG_RF95_CODING_RATE_4_5 0x00
#define BG_RF95_CODING_RATE_4_6 0x08
#define BG_RF95_CODING_RATE_4_7 0x10
#define BG_RF95_CODING_RATE_4_8 0x18
#define BG_RF95_CODING_RATE_4_5 0x02
#define BG_RF95_CODING_RATE_4_6 0x04
#define BG_RF95_CODING_RATE_4_7 0x06
#define BG_RF95_CODING_RATE_4_8 0x08
#define BG_RF95_IMPLICIT_HEADER_MODE_ON 0x04
#define BG_RF95_RX_PAYLOAD_CRC_ON 0x02
#define BG_RF95_LOW_DATA_RATE_OPTIMIZE 0x01
@ -547,6 +547,8 @@ public:
Bw31_25Cr48Sf512, ///< Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range
Bw125Cr48Sf4096, ///< Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
Bw125Cr45Sf4096, ///< APRS
Bw125Cr45Sf2048, ///<Bw = 125 kHz Cr = 4/5, Sf= 2048 chips/symbol, CRC on.
Bw250Cr48Sf4096, ///< Bw = 250 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on.
} ModemConfigChoice;
/// Constructor. You can have multiple instances, but each instance must have its own

Binary file not shown.

Binary file not shown.

BIN
pdf/LilyGo_TBeam_V0.7.pdf Normal file

Binary file not shown.

BIN
pdf/LilyGo_TBeam_V1.0.pdf Normal file

Binary file not shown.

BIN
pdf/LilyGo_TBeam_V1.1.pdf Normal file

Binary file not shown.

View File

@ -9,9 +9,8 @@
; https://docs.platformio.org/page/projectconf.html
[env]
platform = espressif32 @ 3.0.0
platform = espressif32 @ 3.1.1
framework = arduino
monitor_speed = 115200
build_flags = -Wl,--gc-sections,--relax
board_build.partitions = partitions.csv
@ -29,17 +28,32 @@ lib_deps =
Adafruit GFX Library
Adafruit Unified Sensor
AXP202X_Library
SparkFun u-blox Arduino Library
[env:ttgo-t-beam-v1.0]
board = ttgo-t-beam
build_flags = ${env.build_flags} -DT_BEAM_V1_0
build_flags = ${env.build_flags} -D T_BEAM_V1_0
[env:ttgo-t-beam-v0.7]
board = ttgo-t-beam
build_flags = ${env.build_flags} -DT_BEAM_V0_7
build_flags = ${env.build_flags} -D T_BEAM_V0_7
[env:ttgo-lora32-v2.1]
board = ttgo-lora32-v21
build_flags = ${env.build_flags} -D LORA32_21
[env:ttgo-lora32-v2]
board = ttgo-lora32-v1
board = ttgo-lora32-v2
build_flags = ${env.build_flags} -D LORA32_2
[env:ttgo-lora32-v1]
board = ttgo-lora32-v1
board = ttgo-lora32-v1
build_flags = ${env.build_flags} -D LORA32_1
[env:Heltec-WiFi-v1]
board = heltec_wifi_kit_32
build_flags = ${env.build_flags} -D HELTEC_V1
[env:Heltec-WiFi-v2]
board = heltec_wifi_kit_32_v2
build_flags = ${env.build_flags} -D HELTEC_V2

View File

@ -22,41 +22,64 @@
#include <gfxfont.h>
#include <axp20x.h>
#include "taskGPS.h"
#include "version.h"
#ifdef KISS_PROTOCOL
#include "taskTNC.h"
#endif
#ifdef ENABLE_WIFI
#include "taskWebServer.h"
#endif
#include "version.h"
// I2C LINES
#define I2C_SDA 21
#define I2C_SCL 22
// DISPLAY address
#define SSD1306_ADDRESS 0x3C
// LED for signalling
// IO config
#ifdef T_BEAM_V1_0
const byte TXLED = 4; //pin number for LED on TX Tracker
#else
const byte TXLED = 14; //pin number for LED on TX Tracker
#endif
// Button of TTGO T-Beam
#ifdef T_BEAM_V1_0
#define BUTTON 38 //pin number for Button on TTGO T-Beam
#else
#define BUTTON 39 //pin number for Button on TTGO T-Beam
#define I2C_SDA 21
#define I2C_SCL 22
#define BUTTON 38 //pin number for Button on TTGO T-Beam
#define BUZZER 15 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#endif
#ifdef T_BEAM_V0_7
#define I2C_SDA 21
#define I2C_SCL 22
#define BUTTON 39 //pin number for Button on TTGO T-Beam
#define BUZZER 15 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#elif LORA32_21
#define I2C_SDA 4
#define I2C_SCL 15
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#elif LORA32_2
#define I2C_SDA 21
#define I2C_SCL 22
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#elif LORA32_1
#define I2C_SDA 21
#define I2C_SCL 22
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#elif HELTEC_V1
#define I2C_SDA 4
#define I2C_SCL 15
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#elif HELTEC_V2
#define I2C_SDA 4
#define I2C_SCL 15
#define BUTTON 2 //pin number for BUTTO
#define BUZZER 13 // enter your buzzer pin gpio
const byte TXLED = 4; //pin number for LED on TX Tracker
#endif
// Pins for LoRa module
const byte lora_PReset = 23; //pin where LoRa device reset line is connected
const byte lora_PNSS = 18; //pin number where the NSS line for the LoRa device is connected.
// Variables for APRS packaging
String Tcall; //your Call Sign for normal position reports
String Tcall; //your Call Sign for normal position reports
String aprsSymbolTable = APRS_SYMBOL_TABLE;
String aprsSymbol = APRS_SYMBOL;
String relay_path;
@ -67,6 +90,8 @@ boolean gps_state = true;
boolean key_up = true;
boolean t_lock = false;
boolean fixed_beacon_enabled = false;
boolean show_cmt = true;
#ifdef SHOW_ALT
boolean showAltitude = true;
#else
@ -77,6 +102,16 @@ boolean fixed_beacon_enabled = false;
#else
boolean showBattery = false;
#endif
#ifdef ENABLE_BLUETOOTH
boolean enable_bluetooth = true;
#else
boolean enable_bluetooth = false;
#endif
#ifdef ENABLE_OLED
boolean enabled_oled = true;
#else
boolean enabled_oled = false;
#endif
// Variables and Constants
String loraReceivedFrameString = ""; //data on buff is copied to this string
@ -107,6 +142,7 @@ byte lora_TXPacketL; //length of packet to send, includes source, destin
unsigned long lastTX = 0L;
float BattVolts;
float InpVolts;
// variables for smart beaconing
float average_speed[5] = {0,0,0,0,0}, average_speed_final=0, max_speed=30, min_speed=0;
@ -120,6 +156,12 @@ ulong next_fixed_beacon = 0;
ulong fix_beacon_interval = FIX_BEACON_INTERVAL;
ulong showRXTime = SHOW_RX_TIME;
ulong time_delay = 0;
ulong shutdown_delay = 0;
ulong shutdown_delay_time = 10000;
ulong shutdown_countdown_timer = 0;
boolean shutdown_active =true;
boolean shutdown_countdown_timer_enable = false;
boolean shutdown_usb_status_bef = false;
#define ANGLE 60 // angle to send packet at smart beaconing
#define ANGLE_AVGS 3 // angle averaging - x times
float average_course[ANGLE_AVGS];
@ -130,7 +172,6 @@ uint8_t txPower = TXdbmW;
tWebServerCfg webServerCfg;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_6;
static const adc_unit_t unit = ADC_UNIT_1;
#ifdef T_BEAM_V1_0
@ -141,7 +182,7 @@ static const adc_unit_t unit = ADC_UNIT_1;
uint8_t loraReceivedLength = sizeof(lora_RXBUFF);
// Singleton instance of the radio driver
BG_RF95 rf95(18, 26); // TTGO T-Beam has NSS @ Pin 18 and Interrupt IO @ Pin26
BG_RF95 rf95(18, 26); // TTGO T-Beam has NSS @ Pin 18 and Interrupt IO @ Pin26
// initialize OLED display
#define OLED_RESET 16 // not used
@ -177,11 +218,11 @@ void prepareAPRSFrame(){
Tcourse=gps.course.deg();
Tspeed=gps.speed.knots();
if(Tlat<0) { Ns = "S"; } else { Ns = "N"; }
if(Tlon<0) { Ew = "W"; } else { Ew = "E"; }
if(Tlat < 0) { Tlat= -Tlat; }
//if(Tlat<0) { Ns = "S"; } else { Ns = "N"; }
//if(Tlon<0) { Ew = "W"; } else { Ew = "E"; }
//if(Tlat < 0) { Tlat= -Tlat; }
if(Tlon < 0) { Tlon= -Tlon; }
//if(Tlon < 0) { Tlon= -Tlon; }
aprs_lat = 900000000 - Tlat * 10000000;
aprs_lat = aprs_lat / 26 - aprs_lat / 2710 + aprs_lat / 15384615;
aprs_lon = 900000000 + Tlon * 10000000 / 2;
@ -191,9 +232,9 @@ void prepareAPRSFrame(){
outString += Tcall;
if (relay_path) {
outString += ">APLM0," + relay_path + ":!";
outString += ">APLS01," + relay_path + ":!";
} else {
outString += ">APLM0:!";
outString += ">APLS01:!";
}
if(gps_state && gps.location.isValid()) {
@ -227,8 +268,10 @@ void prepareAPRSFrame(){
outString += aprsLonPreset;
outString += aprsSymbol;
}
outString += aprsComment;
if(show_cmt){
outString += aprsComment;
}
if (showBattery) {
outString += " Batt=";
outString += String(BattVolts, 2);
@ -242,7 +285,28 @@ void prepareAPRSFrame(){
#endif
}
#ifdef BUZZER
/**
* Buzzer sound playback
* @param melody - must be an array. Consisting of an even number of values. frequency and duration
* @param array_size - number of elements in the array
*/
void buzzer(int* melody, int array_size){
for(int i=0; i<array_size; i+=2){
ledcWriteTone(0, *melody);
melody++;
delay(*melody);
melody++;
}
ledcWriteTone(0,0); // turn off buzzer
}
#endif
void sendpacket(){
#ifdef BUZZER
int melody[] = {1000, 50, 800, 100};
buzzer(melody, sizeof(melody)/sizeof(int));
#endif
batt_read();
prepareAPRSFrame();
loraSend(txPower, TXFREQ, outString); //send the packet, data is in TXbuff from lora_TXStart to lora_TXEnd
@ -255,7 +319,9 @@ void sendpacket(){
* @param message
*/
void loraSend(byte lora_LTXPower, float lora_FREQ, const String &message) {
digitalWrite(TXLED, LOW);
#ifdef ENABLE_LED_SIGNALING
digitalWrite(TXLED, LOW);
#endif
lastTX = millis();
int messageSize = min(message.length(), sizeof(lora_TXBUFF) - 1);
@ -265,12 +331,15 @@ void loraSend(byte lora_LTXPower, float lora_FREQ, const String &message) {
rf95.setTxPower(lora_LTXPower);
rf95.sendAPRS(lora_TXBUFF, messageSize);
rf95.waitPacketSent();
digitalWrite(TXLED, HIGH);
#ifdef ENABLE_LED_SIGNALING
digitalWrite(TXLED, HIGH);
#endif
}
void batt_read(){
#ifdef T_BEAM_V1_0
BattVolts = axp.getBattVoltage()/1000;
InpVolts = axp.getVbusVoltage()/1000;
#else
BattVolts = analogRead(35)*7.221/4096;
#endif
@ -280,7 +349,9 @@ void writedisplaytext(String HeaderTxt, String Line1, String Line2, String Line3
batt_read();
if (BattVolts < 3.5 && BattVolts > 3.2){
#ifdef T_BEAM_V1_0
# ifdef ENABLE_LED_SIGNALING
axp.setChgLEDMode(AXP20X_LED_BLINK_4HZ);
#endif
#endif
}
display.clearDisplay();
@ -299,6 +370,13 @@ void writedisplaytext(String HeaderTxt, String Line1, String Line2, String Line3
display.println(Line4);
display.setCursor(0,56);
display.println(Line5);
if (enabled_oled){
//axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // enable oled
display.dim(true);
}else{
//axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); // disable oled
display.dim(false);
}
display.display();
time_to_refresh = millis() + showRXTime;
}
@ -307,9 +385,18 @@ void writedisplaytext(String HeaderTxt, String Line1, String Line2, String Line3
String getSatAndBatInfo() {
String line5;
if(gps_state == true){
line5 = "SAT: " + String(gps.satellites.value()) + " BAT: " + String(BattVolts, 1) + "V";
if(InpVolts > 4){
line5 = "SAT: " + String(gps.satellites.value()) + " BAT: " + String(BattVolts, 1) + "V *";
}else{
line5 = "SAT: " + String(gps.satellites.value()) + " BAT: " + String(BattVolts, 1) + "V";
}
}else{
line5 = "SAT: X BAT: " + String(BattVolts, 1) + "V";
if(InpVolts > 4){
line5 = "SAT: X BAT: " + String(BattVolts, 1) + "V *";
}else{
line5 = "SAT: X BAT: " + String(BattVolts, 1) + "V";
}
}
#if defined(ENABLE_BLUETOOTH) && defined(KISS_PROTOCOL)
if (SerialBT.hasClient()){
@ -363,7 +450,7 @@ void sendTelemetryFrame() {
String telemetryEquations = String(":") + Tcall + ":EQNS.0,5.1,3000,0,10,0,0,10,0,0,28,3000,0,10,0";
String telemetryData = String("T#MIC") + String(b_volt) + ","+ String(b_in_c) + ","+ String(b_out_c) + ","+ String(ac_volt) + ","+ String(ac_c) + ",00000000";
String telemetryBase = "";
telemetryBase += Tcall + ">APLM0" + ":";
telemetryBase += Tcall + ">APLS01" + ":";
sendToTNC(telemetryBase + telemetryParamsNames);
sendToTNC(telemetryBase + telemetryUnitNames);
sendToTNC(telemetryBase + telemetryEquations);
@ -375,6 +462,12 @@ void sendTelemetryFrame() {
// + SETUP --------------------------------------------------------------+//
void setup(){
#ifdef BUZZER
ledcSetup(0,1E5,12);
ledcAttachPin(BUZZER,0);
ledcWriteTone(0,0); // turn off buzzer on start
#endif
#ifdef DIGI_PATH
relay_path = DIGI_PATH;
#else
@ -422,6 +515,12 @@ void setup(){
}
showAltitude = preferences.getBool(PREF_APRS_SHOW_ALTITUDE);
if (!preferences.getBool(PREF_APRS_GPS_EN_INIT)){
preferences.putBool(PREF_APRS_GPS_EN_INIT, true);
preferences.putBool(PREF_APRS_GPS_EN, gps_state);
}
gps_state = preferences.getBool(PREF_APRS_GPS_EN);
if (!preferences.getBool(PREF_APRS_SHOW_BATTERY_INIT)){
preferences.putBool(PREF_APRS_SHOW_BATTERY_INIT, true);
preferences.putBool(PREF_APRS_SHOW_BATTERY, showBattery);
@ -446,18 +545,55 @@ void setup(){
}
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_INTERVAL_PRESET) * 1000;
if (!preferences.getBool(PREF_DEV_SHOW_RX_TIME_INIT)){
preferences.putBool(PREF_DEV_SHOW_RX_TIME_INIT, true);
preferences.putInt(PREF_DEV_SHOW_RX_TIME, showRXTime/1000);
}
showRXTime = preferences.getInt(PREF_DEV_SHOW_RX_TIME) * 1000;
if (!preferences.getBool(PREF_DEV_AUTO_SHUT_PRESET_INIT)){
preferences.putBool(PREF_DEV_AUTO_SHUT_PRESET_INIT, true);
preferences.putInt(PREF_DEV_AUTO_SHUT_PRESET, shutdown_delay_time/1000);
}
shutdown_delay_time = preferences.getInt(PREF_DEV_AUTO_SHUT_PRESET) * 1000;
if (!preferences.getBool(PREF_DEV_AUTO_SHUT_INIT)){
preferences.putBool(PREF_DEV_AUTO_SHUT_INIT, true);
preferences.putBool(PREF_DEV_AUTO_SHUT, shutdown_active);
}
shutdown_active = preferences.getBool(PREF_DEV_AUTO_SHUT);
if (clear_preferences){
delay(1000);
if(digitalRead(BUTTON)==LOW){
clear_preferences = 2;
}
}
if (!preferences.getBool(PREF_APRS_SHOW_CMT_INIT)){
preferences.putBool(PREF_APRS_SHOW_CMT_INIT, true);
preferences.putBool(PREF_APRS_SHOW_CMT, show_cmt);
}
show_cmt = preferences.getBool(PREF_APRS_SHOW_CMT);
if (!preferences.getBool(PREF_DEV_BT_EN_INIT)){
preferences.putBool(PREF_DEV_BT_EN_INIT, true);
preferences.putBool(PREF_DEV_BT_EN, enable_bluetooth);
}
enable_bluetooth = preferences.getBool(PREF_DEV_BT_EN);
if (!preferences.getBool(PREF_DEV_OL_EN_INIT)){
preferences.putBool(PREF_DEV_OL_EN_INIT, true);
preferences.putBool(PREF_DEV_OL_EN,enabled_oled);
}
enabled_oled = preferences.getBool(PREF_DEV_OL_EN);
#endif
for (int i=0;i<ANGLE_AVGS;i++) { // set average_course to "0"
@ -465,7 +601,13 @@ void setup(){
}
pinMode(TXLED, OUTPUT);
pinMode(BUTTON, INPUT);
#ifdef T_BEAM_V1_0
pinMode(BUTTON, INPUT);
#elif T_BEAM_V0_7
pinMode(BUTTON, INPUT);
#else
pinMode(BUTTON, INPUT_PULLUP);
#endif
digitalWrite(TXLED, LOW); // turn blue LED off
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
@ -473,35 +615,39 @@ void setup(){
#ifdef T_BEAM_V1_0
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
}
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON);
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LoRa
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // switch on GPS
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
axp.setDCDC1Voltage(3300);
// Enable ADC to measure battery current, USB voltage etc.
axp.adc1Enable(0xfe, true);
axp.adc2Enable(0x80, true);
axp.setChgLEDMode(AXP20X_LED_OFF);
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // oled do not turn off
#endif
if(!display.begin(SSD1306_SWITCHCAPVCC, SSD1306_ADDRESS)) {
for(;;); // Don't proceed, loop forever
}
#ifdef ENABLE_PREFERENCES
if (clear_preferences == 2){
writedisplaytext("LoRa-APRS","","","Factory reset","","");
delay(1000);
if(digitalRead(BUTTON)==LOW){
clear_preferences = 3;
preferences.clear();
preferences.end();
writedisplaytext("LoRa-APRS","","Factory reset","Done!","","");
delay(2000);
ESP.restart();
} else {
writedisplaytext("LoRa-APRS","","Factory reset","Cancel","","");
delay(2000);
}
//#ifdef T_BEAM_V1_0
if(digitalRead(BUTTON)==LOW){
clear_preferences = 3;
preferences.clear();
preferences.end();
writedisplaytext("LoRa-APRS","","Factory reset","Done!","","");
delay(2000);
ESP.restart();
} else {
writedisplaytext("LoRa-APRS","","Factory reset","Cancel","","");
delay(2000);
}
//#endif
}
#endif
writedisplaytext("LoRa-APRS","","Init:","Display OK!","","");
@ -541,16 +687,21 @@ void setup(){
xTaskCreatePinnedToCore(taskTNC, "taskTNC", 10000, nullptr, 1, nullptr, xPortGetCoreID());
#endif
#if defined(ENABLE_BLUETOOTH) && defined(KISS_PROTOCOL)
#ifdef BLUETOOTH_PIN
SerialBT.setPin(BLUETOOTH_PIN);
#endif
SerialBT.begin(String("TTGO LORA APRS ") + Tcall);
writedisplaytext("LoRa-APRS","","Init:","BT OK!","","");
#if defined(KISS_PROTOCOL)
if (enable_bluetooth){
#ifdef BLUETOOTH_PIN
SerialBT.setPin(BLUETOOTH_PIN);
#endif
#ifdef ENABLE_BLUETOOTH
SerialBT.begin(String("TTGO LORA APRS ") + Tcall);
writedisplaytext("LoRa-APRS","","Init:","BT OK!","","");
#endif
}
#endif
#ifdef ENABLE_WIFI
webServerCfg = {.callsign = Tcall};
xTaskCreate(taskWebServer, "taskWebServer", 40000, (void*)(&webServerCfg), 1, nullptr);
xTaskCreate(taskWebServer, "taskWebServer", 42000, (void*)(&webServerCfg), 1, nullptr);
writedisplaytext("LoRa-APRS","","Init:","WiFi task started"," =:-) ","");
#endif
@ -559,9 +710,6 @@ void setup(){
time_to_refresh = millis() + showRXTime;
displayInvalidGPS();
digitalWrite(TXLED, HIGH);
#ifdef T_BEAM_V1_0
axp.setChgLEDMode(AXP20X_LED_OFF);
#endif
}
// +---------------------------------------------------------------------+//
@ -597,6 +745,8 @@ void loop() {
#endif
writedisplaytext("((GPSOFF))","","","","","");
next_fixed_beacon = millis() + fix_beacon_interval;
preferences.putBool(PREF_APRS_GPS_EN_INIT, false);
preferences.putBool(PREF_APRS_GPS_EN, false);
}else{
gps_state = true;
@ -604,6 +754,8 @@ void loop() {
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
#endif
writedisplaytext("((GPS ON))","","","","",""); // GPS ON
preferences.putBool(PREF_APRS_GPS_EN_INIT, true);
preferences.putBool(PREF_APRS_GPS_EN, true);
}
}
@ -620,6 +772,29 @@ void loop() {
}
}
#ifdef T_BEAM_V1_0
if(shutdown_active){
if(InpVolts> 4){
shutdown_usb_status_bef = true;
shutdown_countdown_timer_enable = false;
}
if(InpVolts < 4 && shutdown_usb_status_bef == true){
shutdown_usb_status_bef = false;
shutdown_countdown_timer_enable = true;
shutdown_countdown_timer = millis() + shutdown_delay_time;
}
if(shutdown_countdown_timer_enable){
if(millis() >= shutdown_countdown_timer){
axp.shutdown();
}
}
}
#endif
#ifdef KISS_PROTOCOL
String *TNC2DataFrame = nullptr;
if (tncToSendQueue) {
@ -634,7 +809,13 @@ void loop() {
if (rf95.waitAvailableTimeout(100)) {
#ifdef T_BEAM_V1_0
axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
#ifdef ENABLE_LED_SIGNALING
axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
#endif
#endif
#ifdef BUZZER
int melody[] = {300, 50, 500, 100};
buzzer(melody, sizeof(melody)/sizeof(int));
#endif
#ifdef SHOW_RX_PACKET // only show RX packets when activitated in config
loraReceivedLength = sizeof(lora_RXBUFF); // reset max length before receiving!
@ -652,7 +833,9 @@ void loop() {
}
#endif
#ifdef T_BEAM_V1_0
axp.setChgLEDMode(AXP20X_LED_OFF);
#ifdef ENABLE_LED_SIGNALING
axp.setChgLEDMode(AXP20X_LED_OFF);
#endif
#endif
}

View File

@ -1,35 +1,44 @@
// Tracker for LoRA APRS
// from OE1ACM and OE3CJB redesigned by SQ9MDD
// KISS ans Bluetooth by SQ5RWU
// TTGO T-Beam v1.0 only
//
// licensed under CC BY-NC-SA
// USER DATA - USE THESE LINES TO MODIFY YOUR PREFERENCES
#define KISS_PROTOCOL // If enabled send and receive data in SIMPLE KISS format to serial port
#define CALLSIGN "NOCALL-0" // enter your callsign here - less then 6 letter callsigns please add "spaces" so total length is 6 (without SSID)
#define DIGI_PATH "WIDE1-1" // one hope please (WIDE1-1)
#define FIXED_BEACON_EN // allows cyclic sending of a bicon when GPS is turned off
#define LATIDUDE_PRESET "0000.00N" // please in APRS notation: DDMM.mmN or DDMM.mmS (used for manual or fixed beacon sending)
#define LONGITUDE_PRESET "00000.00E" // please in APRS notation: DDDMM.mmE or DDDMM.mmW (used for manual or fixed beacon sending)
#define APRS_SYMBOL_TABLE "/" // set primary or secondary symbols table
#define APRS_SYMBOL "[" // other symbols are: "[" => RUNNER, "b" => BICYCLE, "<" => MOTORCYCLE, "R" => Recreation Vehicle
#define MY_COMMENT "Lora Tracker" // add your coment here - if empty then no comment is sent max 64 bytes
//#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 TXFREQ 433.775 // Set transmit frequency in MHz
#define TXdbmW 20 // Set transmit power in dBm 17-50mW, 18-63mW, 19-80mW, 20-100mW
#define ENABLE_BLUETOOTH // bluetooth KISS interface enable
//#define BLUETOOTH_PIN "0000" // bluetooth pairing pin
//#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 KISS_DEBUG //
#define ENABLE_WIFI // enable WiFi conection
#define NETWORK_TNC_PORT 8001 // Set KISS TCP Port
//#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
#define TNC_SELF_TELEMETRY_INTERVAL (5 * 60 * 1000) //
// Please do not edit this file. !!!!!!!
// Configuration shuld be done via www. Default WiFi pasword for AP is: xxxxxxxxxx
#define KISS_PROTOCOL // If enabled send and receive data in SIMPLE KISS format to serial, bluetooth and tcp port
#define CALLSIGN "N0CALL-0" // this option is available via WWW // enter your callsign here - less then 6 letter callsigns please add "spaces" so total length is 6 (without SSID)
#define DIGI_PATH "ECHO" // this option is available via WWW // one hope, please use simple ECHO alias
#define FIXED_BEACON_EN // this option is available via WWW // allows cyclic sending of a bicon when GPS is turned off
#define LATIDUDE_PRESET "0000.00N" // this option is available via WWW // please in APRS notation: DDMM.mmN or DDMM.mmS (used for manual or fixed beacon sending)
#define LONGITUDE_PRESET "00000.00E" // this option is available via WWW // please in APRS notation: DDDMM.mmE or DDDMM.mmW (used for manual or fixed beacon sending)
#define APRS_SYMBOL_TABLE "/" // this option is available via WWW // set primary or secondary symbols table
#define APRS_SYMBOL "[" // this option is available via WWW // other symbols are: "[" => RUNNER, "b" => BICYCLE, "<" => MOTORCYCLE, "R" => Recreation Vehicle
#define MY_COMMENT "Lora Tracker" // this option is available via WWW // add your coment here - if empty then no comment is sent max 64 bytes
#define SHOW_ALT // this option is available via WWW // send Altitude in frame
#define SHOW_BATT // this option is available via WWW // send battery voltage at the end of comment (we need beggining for QSY message format)
#define SHOW_RX_PACKET // this option is available via WWW // uncomment to show received LoRa APS packets for the time given below
#define SHOW_RX_TIME 10000 // this option is available via WWW // show RX packet for milliseconds (5000 = 5secs)
#define TXFREQ 433.775 // Set transmit frequency in MHz
#define TXdbmW 20 // Set transmit power in dBm 17-50mW, 18-63mW, 19-80mW, 20-100mW
#define ENABLE_OLED // this option is available via WWW // enable oled
#define ENABLE_LED_SIGNALING // enable red and blue led signalling
//#define ENABLE_TNC_SELF_TELEMETRY //
// #define LOCAL_KISS_ECHO // echoing KISS frame back
//#define KISS_DEBUG //
#define NETWORK_TNC_PORT 8001 // Set KISS TCP Port
//#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
//#define TNC_SELF_TELEMETRY_INTERVAL (5 * 60 * 1000) //
#ifdef T_BEAM_V1_0
#define ENABLE_WIFI // enable WiFi conection do not turn off
#define ENABLE_BLUETOOTH // if enabled here this option is available via WWW // bluetooth KISS interface enabl
//#define BLUETOOTH_PIN "0000" // bluetooth pairing pin
#elif T_BEAM_V0_7
#define ENABLE_WIFI // enable WiFi conection do not turn off
#define ENABLE_BLUETOOTH // if enabled here this option is available via WWW // bluetooth KISS interface enabl
//#define BLUETOOTH_PIN "0000" // bluetooth pairing pin
#else
#define ENABLE_WIFI // enable WiFi conection
//#define ENABLE_BLUETOOTH // Lora32 board WiFi or Bluetooth
//#define BLUETOOTH_PIN "0000" // bluetooth pairing pin
#endif

View File

@ -1,11 +1,14 @@
#include <taskGPS.h>
#include "TTGO_T-Beam_LoRa_APRS_config.h"
#include <SparkFun_Ublox_Arduino_Library.h>
SFE_UBLOX_GPS myGPS;
// Pins for GPS
#ifdef T_BEAM_V1_0
static const int RXPin = 12, TXPin = 34;
static const int RXPin = 12, TXPin = 34;
#else
static const int RXPin = 15, TXPin = 12;
static const int RXPin = 15, TXPin = 12;
#endif
static const uint32_t GPSBaud = 9600; //GPS
HardwareSerial gpsSerial(1); // TTGO has HW serial
@ -15,7 +18,24 @@ bool gpsInitialized = false;
void taskGPS(void *parameter) {
if (!gpsInitialized){
gpsSerial.begin(GPSBaud, SERIAL_8N1, TXPin, RXPin); //Startup HW serial for GPS
// set GPS parameters on restart
// Thanks Peter (https://github.com/peterus)
// https://github.com/lora-aprs/TTGO-T-Beam_GPS-reset
if(myGPS.begin(gpsSerial)){
myGPS.setUART1Output(COM_TYPE_NMEA); //Set the UART port to output NMEA only
//myGPS.saveConfiguration(); //Save the current settings to flash and BBR
myGPS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_UART1);
myGPS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_UART1);
myGPS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_UART1);
myGPS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_UART1);
myGPS.disableNMEAMessage(UBX_NMEA_RMC, COM_PORT_UART1);
myGPS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_UART1);
//myGPS.saveConfiguration(); //Save the current settings to flash and BBR
delay(1000);
}
}
for (;;) {
while (gpsSerial.available() > 0) {
gps.encode(gpsSerial.read());

View File

@ -118,6 +118,13 @@ void handle_Cfg() {
jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_BATTERY);
jsonData += jsonLineFromPreferenceBool(PREF_APRS_FIXED_BEACON_PRESET);
jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_ALTITUDE);
jsonData += jsonLineFromPreferenceBool(PREF_APRS_GPS_EN);
jsonData += jsonLineFromPreferenceBool(PREF_DEV_OL_EN);
jsonData += jsonLineFromPreferenceBool(PREF_APRS_SHOW_CMT);
jsonData += jsonLineFromPreferenceBool(PREF_DEV_BT_EN);
jsonData += jsonLineFromPreferenceInt(PREF_DEV_SHOW_RX_TIME);
jsonData += jsonLineFromPreferenceBool(PREF_DEV_AUTO_SHUT);
jsonData += jsonLineFromPreferenceInt(PREF_DEV_AUTO_SHUT_PRESET);
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);
@ -151,14 +158,29 @@ void handle_SaveAPRSCfg() {
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));
preferences.putBool(PREF_APRS_GPS_EN, server.hasArg(PREF_APRS_GPS_EN));
preferences.putBool(PREF_APRS_SHOW_CMT, server.hasArg(PREF_APRS_SHOW_CMT));
server.sendHeader("Location", "/");
server.send(302,"text/html", "");
}
void handle_saveDeviceCfg(){
preferences.putBool(PREF_DEV_BT_EN, server.hasArg(PREF_DEV_BT_EN));
preferences.putBool(PREF_DEV_OL_EN, server.hasArg(PREF_DEV_OL_EN));
if (server.hasArg(PREF_DEV_SHOW_RX_TIME)){
preferences.putInt(PREF_DEV_SHOW_RX_TIME, server.arg(PREF_DEV_SHOW_RX_TIME).toInt());
}
preferences.putBool(PREF_DEV_AUTO_SHUT, server.hasArg(PREF_DEV_AUTO_SHUT));
if (server.hasArg(PREF_DEV_AUTO_SHUT_PRESET)){
preferences.putInt(PREF_DEV_AUTO_SHUT_PRESET, server.arg(PREF_DEV_AUTO_SHUT_PRESET).toInt());
}
server.sendHeader("Location", "/");
server.send(302,"text/html", "");
}
[[noreturn]] void taskWebServer(void *parameter) {
@ -174,6 +196,7 @@ void handle_SaveAPRSCfg() {
server.on("/reboot", handle_Reboot);
server.on("/cfg", handle_Cfg);
server.on("/save_aprs_cfg", handle_SaveAPRSCfg);
server.on("/save_device_cfg", handle_saveDeviceCfg);
server.on("/restore", handle_Restore);
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");