Compare commits

...

38 Commits

Author SHA1 Message Date
Ricardo Guzman (Richonguzman)
0eec028c5d update SENSOR BUS 2026-02-23 12:00:55 -03:00
Ricardo Guzman (Richonguzman)
c48dd15bd6 better ADC and VEXT control 2026-02-23 11:14:42 -03:00
Ricardo Guzman (Richonguzman)
f26ded5b5c less memory fixes too 2026-02-20 17:36:26 -03:00
Ricardo Guzman (Richonguzman)
c887689406 indexOf transformation 2026-02-20 17:03:39 -03:00
Ricardo Guzman (Richonguzman)
775e08a10a stationCallsignIsValid 2026-02-20 10:03:01 -03:00
Ricardo Guzman (Richonguzman)
f9291821d2 2 decimales for QTH query 2026-02-18 11:03:06 -03:00
Ricardo Guzman (Richonguzman)
12d0bb760e version update 2026-02-16 23:46:03 -03:00
Ricardo Guzman (Richonguzman)
f020eb7491 update a nombre CPU 2026-02-16 23:01:05 -03:00
Ricardo Guzman (Richonguzman)
63f4660ef6 power utils update con cpu 2026-02-16 22:48:28 -03:00
Ricardo Guzman (Richonguzman)
efabe9b1f7 start Heltec V2 915 2026-02-16 21:37:54 -03:00
Ricardo Guzman (Richonguzman)
beae88d557 less time 2026-02-11 01:03:54 -03:00
Ricardo Guzman (Richonguzman)
8b4d8c2d1d day reset of status tx 2026-02-10 23:01:49 -03:00
Ricardo Guzman (Richonguzman)
08ae1e322b Symbol Explanation added to index.html 2026-02-03 17:09:27 -03:00
Ricardo Guzman (Richonguzman)
d576be0f2b fix telemetry tactical callsign 2026-01-31 11:47:27 -03:00
Ricardo Guzman (Richonguzman)
7c9903ac12 WEBUI update 2026-01-20 22:44:03 -03:00
Ricardo Guzman (Richonguzman)
0d7cff14f5 lastServerCheck update 2026-01-20 21:19:53 -03:00
Ricardo Guzman (Richonguzman)
5c89635a23 lastServerCheck 2026-01-20 21:08:28 -03:00
Ricardo Guzman (Richonguzman)
7a35f9e32a Server Alive mod 2026-01-20 20:56:20 -03:00
Ricardo Guzman (Richonguzman)
7695675a7c check server 2026-01-20 09:50:09 -03:00
Ricardo Guzman (Richonguzman)
c8c0be636d check internet connection 2026-01-20 00:16:24 -03:00
Ricardo Guzman (Richonguzman)
76fe27a0ab APRSSSR into APRSSR fix 2026-01-16 09:41:20 -03:00
Ricardo Guzman (Richonguzman)
da80391921 change Freq with bandWidth fix 2026-01-13 01:50:12 -03:00
Ricardo Guzman (Richonguzman)
d638093dbf Tactical 6 update 2026-01-11 11:46:23 -03:00
Ricardo Guzman (Richonguzman)
66a5f03c12 de update for tactical 2026-01-09 00:02:29 -03:00
Ricardo Guzman (Richonguzman)
ce8cf3a2fe minimal interval updated 2026-01-08 14:08:07 -03:00
Ricardo Guzman (Richonguzman)
4b45b90c88 minor path updates 2026-01-08 12:21:19 -03:00
Ricardo Guzman (Richonguzman)
dbe980a081 tactical callsign ready for testing 2026-01-07 23:18:14 -03:00
Ricardo Guzman (Richonguzman)
bb3d59a20d digi tactical changes 2026-01-07 17:25:45 -03:00
Ricardo Guzman (Richonguzman)
fe590b41b0 tactical callsign displayShow 2026-01-07 14:30:32 -03:00
Ricardo Guzman (Richonguzman)
3f76005949 few delays killed 2026-01-07 12:19:51 -03:00
Ricardo Guzman (Richonguzman)
6d95231b9c web mods for tactical 2026-01-07 11:53:10 -03:00
Ricardo Guzman (Richonguzman)
81692010cf tactical validation 2026-01-07 11:44:00 -03:00
Ricardo Guzman (Richonguzman)
50b738d04b Spreading Factor update 2026-01-07 10:37:11 -03:00
Ricardo Guzman (Richonguzman)
026d6b2eeb starting Heltec V4 2026-01-07 10:14:42 -03:00
Ricardo Guzman (Richonguzman)
fe705519cb V3.1.7 OTA and mode 2025-12-29 09:10:17 -03:00
Ricardo Guzman (Richonguzman)
1fa74b8697 GPS encoded payload comment fix 2025-12-28 13:45:29 -03:00
Ricardo Guzman (Richonguzman)
a3794085b4 OTA update fixed 2025-12-28 11:59:05 -03:00
Ricardo Guzman (Richonguzman)
0a898a40e6 gps payload decoding fix2 2025-12-28 11:46:43 -03:00
73 changed files with 1021 additions and 804 deletions

View File

@@ -51,6 +51,8 @@ ____________________________________________________
<br /> <br />
# Timeline (Versions): # Timeline (Versions):
- 2026-01-07 Tactical Callsign added.
- 2026-01-05 Heltec V4 support added.
- 2025-12-22 Heltec Wireless Paper V1.2 and VisionMaster E290 Added. Thanks HA5SZI. - 2025-12-22 Heltec Wireless Paper V1.2 and VisionMaster E290 Added. Thanks HA5SZI.
- 2025-12-18 TCXO and packet decoding updates. - 2025-12-18 TCXO and packet decoding updates.
- 2025-12-01 APRSPacketLib updates, AHT20 sensor added, INA219 support added. - 2025-12-01 APRSPacketLib updates, AHT20 sensor added, INA219 support added.

View File

@@ -31,12 +31,12 @@ lib_deps =
adafruit/Adafruit INA219 @ 1.2.3 adafruit/Adafruit INA219 @ 1.2.3
adafruit/Adafruit Si7021 Library @ 1.5.3 adafruit/Adafruit Si7021 Library @ 1.5.3
arduino-libraries/NTPClient @ 3.2.1 arduino-libraries/NTPClient @ 3.2.1
ayushsharma82/ElegantOTA @ 3.1.5 ayushsharma82/ElegantOTA @ 3.1.7
bblanchon/ArduinoJson @ 6.21.3 bblanchon/ArduinoJson @ 6.21.3
jgromes/RadioLib @ 7.1.0 jgromes/RadioLib @ 7.1.0
knolleary/PubSubClient @ 2.8 knolleary/PubSubClient @ 2.8
mathieucarbou/AsyncTCP @ 3.2.5 ESP32Async/AsyncTCP @ 3.4.9
mathieucarbou/ESPAsyncWebServer @ 3.2.3 ESP32Async/ESPAsyncWebServer @ 3.9.3
mikalhart/TinyGPSPlus @ 1.0.3 mikalhart/TinyGPSPlus @ 1.0.3
richonguzman/APRSPacketLib @ 1.0.4 richonguzman/APRSPacketLib @ 1.0.4
display_libs = display_libs =

View File

@@ -36,7 +36,8 @@
"blacklist": "", "blacklist": "",
"digi": { "digi": {
"mode": 0, "mode": 0,
"ecoMode": 0 "ecoMode": 0,
"backupDigiMode": false
}, },
"lora": { "lora": {
"rxActive": true, "rxActive": true,
@@ -113,7 +114,6 @@
}, },
"other": { "other": {
"rememberStationTime": 30, "rememberStationTime": 30,
"backupDigiMode": false,
"rebootMode": false, "rebootMode": false,
"rebootModeTime": 6, "rebootModeTime": 6,
"startupDelay": 0 "startupDelay": 0

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" data-bs-theme="auto"> <html lang="en" data-bs-theme="dark">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -36,8 +36,8 @@
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Backup</a> <a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Backup</a>
<div class="dropdown-menu"> <div class="dropdown-menu">
<a class="dropdown-item" href="#" id="backup">Download</a> <a class="dropdown-item" href="#" id="backup">Download Conf.</a>
<a class="dropdown-item" href="#" id="restore">Restore</a> <a class="dropdown-item" href="#" id="restore">Restore Conf.</a>
</div> </div>
</li> </li>
<li class="nav-item dropdown"> <li class="nav-item dropdown">
@@ -119,7 +119,7 @@
</div> </div>
<div class="col-lg-9 col-sm-12"> <div class="col-lg-9 col-sm-12">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-6">
<label for="callsign" class="form-label" <label for="callsign" class="form-label"
>Callsign - SSID</label >Callsign - SSID</label
> >
@@ -133,6 +133,19 @@
oninput="this.value = this.value.toUpperCase();" oninput="this.value = this.value.toUpperCase();"
/> />
</div> </div>
<div class="col-6">
<label for="tacticalCallsign" class="form-label"
>Tactical Callsign</label
>
<input
type="text"
name="tacticalCallsign"
id="tacticalCallsign"
class="form-control"
placeholder=""
oninput="this.value = this.value.toUpperCase();"
/>
</div>
<div class="col-12 mt-3"> <div class="col-12 mt-3">
<label <label
for="beacon.comment" for="beacon.comment"
@@ -158,7 +171,7 @@
name="beacon.path" name="beacon.path"
id="beacon.path" id="beacon.path"
class="form-control" class="form-control"
placeholder="We prefer WIDE1-1" placeholder="WIDE1-1"
/> />
</div> </div>
<div class="col-8 mt-3"> <div class="col-8 mt-3">
@@ -188,10 +201,10 @@
name="action.symbol" name="action.symbol"
id="action.symbol" id="action.symbol"
> >
<option value="L#">Green star with L</option> <option value="L#">Green Star with L - Digipeater</option>
<option value="L_">Blue circle with L</option> <option value="L_">Blue Circle with L - Station with Wx Data</option>
<option value="L&">Black diamond with L</option> <option value="L&">Black Diamond with L - Rx (only) iGate</option>
<option value="La" selected>Red diamond with L</option> <option value="La" selected>Red Diamond with L - Rx+Tx iGate</option>
</select> </select>
</div> </div>
<div <div
@@ -244,7 +257,7 @@
name="personalNote" name="personalNote"
id="personalNote" id="personalNote"
class="form-control" class="form-control"
placeholder="A couple of words" placeholder="Describe here your Station"
/> />
</div> </div>
<div class="col-12 mt-3"> <div class="col-12 mt-3">
@@ -591,11 +604,11 @@
type="number" type="number"
name="beacon.interval" name="beacon.interval"
id="beacon.interval" id="beacon.interval"
placeholder="15"
class="form-control" class="form-control"
required="" value="15"
min="10"
step="1" step="1"
min="15" required
/> />
<span class="input-group-text" <span class="input-group-text"
>minutes >minutes
@@ -736,6 +749,24 @@
<option value="2">OFF (Normal Mode - WiFiAP disabled but Serial Output still enabled)</option> <option value="2">OFF (Normal Mode - WiFiAP disabled but Serial Output still enabled)</option>
</select> </select>
</div> </div>
<div class="col-12 mt-3">
<div class="form-check form-switch">
<div class="form-text">
If WiFi/server connection is lost in iGate-only mode, the device switches to Digipeater mode (WIDE1-1) and retries connection every 15 minutes.
</div>
<input
type="checkbox"
name="digi.backupDigiMode"
id="digi.backupDigiMode"
class="form-check-input"
/>
<label
for="digi.backupDigiMode"
class="form-label"
>Backup Digipeater Mode</label
>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -853,7 +884,9 @@
id="lora.rxSpreadingFactor" id="lora.rxSpreadingFactor"
required="" required=""
> >
<option value="7">SF7 - Lowest battery usage</option> <option value="5">SF5 - Lowest battery usage</option>
<option value="6">SF6</option>
<option value="7">SF7</option>
<option value="8">SF8</option> <option value="8">SF8</option>
<option value="9">SF9</option> <option value="9">SF9</option>
<option value="10">SF10</option> <option value="10">SF10</option>
@@ -873,7 +906,9 @@
id="lora.txSpreadingFactor" id="lora.txSpreadingFactor"
required="" required=""
> >
<option value="7">SF7 - Lowest battery usage</option> <option value="5">SF5 - Lowest battery usage</option>
<option value="6">SF6</option>
<option value="7">SF7</option>
<option value="8">SF8</option> <option value="8">SF8</option>
<option value="9">SF9</option> <option value="9">SF9</option>
<option value="10">SF10</option> <option value="10">SF10</option>
@@ -2110,52 +2145,6 @@
</div> </div>
</div> </div>
<hr> <hr>
<div class="row my-5 d-flex align-items-top">
<div class="col-lg-3 col-sm-12">
<h5>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-heart-pulse-fill"
viewBox="0 0 16 16"
>
<path
d="M1.475 9C2.702 10.84 4.779 12.871 8 15c3.221-2.129 5.298-4.16 6.525-6H12a.5.5 0 0 1-.464-.314l-1.457-3.642-1.598 5.593a.5.5 0 0 1-.945.049L5.889 6.568l-1.473 2.21A.5.5 0 0 1 4 9z"
/>
<path
d="M.88 8C-2.427 1.68 4.41-2 7.823 1.143q.09.083.176.171a3 3 0 0 1 .176-.17C11.59-2 18.426 1.68 15.12 8h-2.783l-1.874-4.686a.5.5 0 0 0-.945.049L7.921 8.956 6.464 5.314a.5.5 0 0 0-.88-.091L3.732 8z"
/>
</svg>
Experimental
</h5>
<small>You can test new features. <u>Use at your own risk!</u></small>
</div>
<div class="col-lg-9 col-sm-12">
<div class="row">
<div class="col-12">
<div class="form-check form-switch">
<div class="form-text">
When "only" iGate Mode loses WiFi, it will change into a Digipeater Mode and after 15 min check if WiFi available and return to "only" iGate Mode.
</div>
<input
type="checkbox"
name="other.backupDigiMode"
id="other.backupDigiMode"
class="form-check-input"
/>
<label
for="other.backupDigiMode"
class="form-label"
>Backup Digipeater Mode</label
>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</main> </main>
<footer <footer
@@ -2210,7 +2199,7 @@
<a <a
href="https://cd3eap.aguayoki.cl/" href="https://cd3eap.aguayoki.cl/"
target="_blank" target="_blank"
>CD3EAP</a >CA3EAP</a
></b ></b
>: Settings Page. >: Settings Page.
</p> </p>

View File

@@ -54,6 +54,7 @@ function loadSettings(settings) {
currentSettings = settings; currentSettings = settings;
// General // General
document.getElementById("callsign").value = settings.callsign; document.getElementById("callsign").value = settings.callsign;
document.getElementById("tacticalCallsign").value = settings.tacticalCallsign;
document.getElementById("beacon.comment").value = settings.beacon.comment; document.getElementById("beacon.comment").value = settings.beacon.comment;
document.getElementById("beacon.path").value = settings.beacon.path; document.getElementById("beacon.path").value = settings.beacon.path;
document.getElementById("beacon.symbol").value = settings.beacon.symbol; document.getElementById("beacon.symbol").value = settings.beacon.symbol;
@@ -139,6 +140,7 @@ function loadSettings(settings) {
// Digi // Digi
document.getElementById("digi.mode").value = settings.digi.mode; document.getElementById("digi.mode").value = settings.digi.mode;
document.getElementById("digi.ecoMode").value = settings.digi.ecoMode; document.getElementById("digi.ecoMode").value = settings.digi.ecoMode;
document.getElementById("digi.backupDigiMode").checked = settings.digi.backupDigiMode;
// LoRa // LoRa
document.getElementById("lora.rxActive").checked = settings.lora.rxActive; document.getElementById("lora.rxActive").checked = settings.lora.rxActive;
@@ -258,9 +260,6 @@ function loadSettings(settings) {
document.getElementById("ntp.server").value = settings.ntp.server; document.getElementById("ntp.server").value = settings.ntp.server;
document.getElementById("ntp.gmtCorrection").value = settings.ntp.gmtCorrection; document.getElementById("ntp.gmtCorrection").value = settings.ntp.gmtCorrection;
// Experimental
document.getElementById("other.backupDigiMode").checked = settings.other.backupDigiMode;
updateImage(); updateImage();
} }

View File

@@ -69,6 +69,7 @@ class DIGI {
public: public:
int mode; int mode;
int ecoMode; // 0 = Not Active | 1 = Ultra EcoMode | 2 = Not Active (WiFi OFF, Serial ON) int ecoMode; // 0 = Not Active | 1 = Ultra EcoMode | 2 = Not Active (WiFi OFF, Serial ON)
bool backupDigiMode;
}; };
class LoraModule { class LoraModule {
@@ -170,8 +171,8 @@ public:
class Configuration { class Configuration {
public: public:
String callsign; String callsign;
String tacticalCallsign;
int rememberStationTime; int rememberStationTime;
bool backupDigiMode;
bool rebootMode; bool rebootMode;
int rebootModeTime; int rebootModeTime;
int startupDelay; int startupDelay;

View File

@@ -45,7 +45,7 @@ namespace Utils {
void checkRebootMode(); void checkRebootMode();
void checkRebootTime(); void checkRebootTime();
void checkSleepByLowBatteryVoltage(uint8_t mode); void checkSleepByLowBatteryVoltage(uint8_t mode);
bool checkValidCallsign(const String& callsign); bool callsignIsValid(const String& callsign);
void startupDelay(); void startupDelay();
} }

View File

@@ -115,6 +115,8 @@
if (SerialAT.available()) { if (SerialAT.available()) {
String response = SerialAT.readString(); String response = SerialAT.readString();
//Serial.println(response); // DEBUG of Modem AT message //Serial.println(response); // DEBUG of Modem AT message
int responseOKIndex = response.indexOf("OK");
int callsignIndex = ATMessage.indexOf(Config.callsign);
if(response.indexOf("verified") >= 0) { if(response.indexOf("verified") >= 0) {
Serial.println("Logged! (User Validated)\n"); Serial.println("Logged! (User Validated)\n");
displayShow(firstLine, "Connecting APRS-IS...", "---> Logged!", " ", 1000); displayShow(firstLine, "Connecting APRS-IS...", "---> Logged!", " ", 1000);
@@ -122,7 +124,7 @@
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
} else if (ATMessage == "AT+NETOPEN" && response.indexOf("OK") >= 0) { } else if (ATMessage == "AT+NETOPEN" && responseOKIndex >= 0) {
Serial.println("Port Open!"); Serial.println("Port Open!");
displayShow(firstLine, "Opening Port...", "---> Port Open", " ", 0); displayShow(firstLine, "Opening Port...", "---> Port Open", " ", 0);
validAT = true; validAT = true;
@@ -145,14 +147,14 @@
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
} else if (ATMessage.indexOf(Config.callsign) >= 3 && !modemLoggedToAPRSIS && response.indexOf("OK") >= 0 && !stationBeacon) { // login info } else if (callsignIndex >= 3 && !modemLoggedToAPRSIS && responseOKIndex >= 0 && !stationBeacon) { // login info
validAT = true; validAT = true;
delayATMessage = 0; delayATMessage = 0;
} else if (ATMessage.indexOf(Config.callsign) == 0 && !beaconSent && response.indexOf("OK") >= 0 && !stationBeacon) { // self beacon or querys } else if (callsignIndex == 0 && !beaconSent && responseOKIndex >= 0 && !stationBeacon) { // self beacon or querys
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
} else if (stationBeacon && response.indexOf("OK") >= 0) { //upload others beacons } else if (stationBeacon && responseOKIndex >= 0) { //upload others beacons
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;

View File

@@ -67,8 +67,8 @@ ___________________________________________________________________*/
#endif #endif
String versionDate = "2025-12-28"; String versionDate = "2026-02-20";
String versionNumber = "3.1.6.3"; String versionNumber = "3.2";
Configuration Config; Configuration Config;
WiFiClient aprsIsClient; WiFiClient aprsIsClient;
WiFiClient mqttClient; WiFiClient mqttClient;
@@ -86,7 +86,7 @@ WiFi_AP *currentWiFi = &Config.wifiAPs[myWiFiAPIndex];
bool isUpdatingOTA = false; bool isUpdatingOTA = false;
uint32_t lastBatteryCheck = 0; uint32_t lastBatteryCheck = 0;
bool backUpDigiMode = false; bool backupDigiMode = false;
bool modemLoggedToAPRSIS = false; bool modemLoggedToAPRSIS = false;
#ifdef HAS_EPAPER #ifdef HAS_EPAPER
@@ -187,7 +187,7 @@ void loop() {
APRS_IS_Utils::processLoRaPacket(packet); // Send received packet to APRSIS APRS_IS_Utils::processLoRaPacket(packet); // Send received packet to APRSIS
} }
if (Config.loramodule.txActive && (Config.digi.mode == 2 || Config.digi.mode == 3 || backUpDigiMode)) { // If Digi enabled if (Config.loramodule.txActive && (Config.digi.mode == 2 || Config.digi.mode == 3 || backupDigiMode)) { // If Digi enabled
STATION_Utils::clean25SegBuffer(); STATION_Utils::clean25SegBuffer();
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
} }

View File

@@ -42,11 +42,13 @@ extern String fifthLine;
extern String sixthLine; extern String sixthLine;
extern String seventhLine; extern String seventhLine;
extern bool modemLoggedToAPRSIS; extern bool modemLoggedToAPRSIS;
extern bool backUpDigiMode; extern bool backupDigiMode;
extern String versionNumber; extern String versionNumber;
uint32_t lastRxTime = millis(); uint32_t lastRxTime = millis();
bool passcodeValid = false; bool passcodeValid = false;
uint32_t lastServerCheck = 0;
#ifdef HAS_A7670 #ifdef HAS_A7670
extern bool stationBeacon; extern bool stationBeacon;
@@ -94,7 +96,7 @@ namespace APRS_IS_Utils {
if (WiFi.status() == WL_CONNECTED) { if (WiFi.status() == WL_CONNECTED) {
wifiState = "OK"; wifiState = "OK";
} else { } else {
if (backUpDigiMode || Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) { if (backupDigiMode || Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) {
wifiState = "--"; wifiState = "--";
} else { } else {
wifiState = "AP"; wifiState = "AP";
@@ -202,7 +204,7 @@ namespace APRS_IS_Utils {
int firstColonIndex = packet.indexOf(":"); int firstColonIndex = packet.indexOf(":");
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] != '}' && packet.indexOf("TCPIP") == -1) { if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] != '}' && packet.indexOf("TCPIP") == -1) {
const String& Sender = packet.substring(3, packet.indexOf(">")); const String& Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) { if (Sender != Config.callsign && Utils::callsignIsValid(Sender)) {
STATION_Utils::updateLastHeard(Sender); STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2); const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
@@ -274,7 +276,31 @@ namespace APRS_IS_Utils {
return outputPacket; return outputPacket;
} }
void processAckMessage(const String& sender, const String& message) {
String ackPacket = Config.callsign;
ackPacket += ">APLRG1,TCPIP,qAC::";
String senderCallsign = sender;
for (int i = sender.length(); i < 9; i++) {
senderCallsign += ' ';
}
ackPacket += senderCallsign;
ackPacket += ":";
String ackMessage = "ack";
ackMessage += message.substring(message.indexOf("{") + 1);
ackMessage.trim();
ackPacket += ackMessage;
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(ackPacket);
#else
upload(ackPacket);
#endif
}
void processAPRSISPacket(const String& packet) { void processAPRSISPacket(const String& packet) {
uint32_t currentTime = millis();
if (!passcodeValid && packet.indexOf(Config.callsign) != -1) { if (!passcodeValid && packet.indexOf(Config.callsign) != -1) {
if (packet.indexOf("unverified") != -1 ) { if (packet.indexOf("unverified") != -1 ) {
Serial.println("\n****APRS PASSCODE NOT VALID****\n"); Serial.println("\n****APRS PASSCODE NOT VALID****\n");
@@ -282,93 +308,79 @@ namespace APRS_IS_Utils {
aprsIsClient.stop(); aprsIsClient.stop();
Config.aprs_is.active = false; Config.aprs_is.active = false;
} else if (packet.indexOf("verified") != -1 ) { } else if (packet.indexOf("verified") != -1 ) {
if (Config.digi.backupDigiMode) lastServerCheck = currentTime;
passcodeValid = true; passcodeValid = true;
} }
} }
if (passcodeValid && !packet.startsWith("#")) { if (passcodeValid) {
if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) { if (packet.startsWith("#")) {
String Sender = packet.substring(0, packet.indexOf(">")); if (Config.digi.backupDigiMode) lastServerCheck = currentTime;
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2); } else {
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) {
Addressee.trim(); String Sender = packet.substring(0, packet.indexOf(">"));
if (Addressee == Config.callsign) { // its for me! const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String receivedMessage; String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
if (AddresseeAndMessage.indexOf("{") > 0) { // ack? Addressee.trim();
String ackMessage = "ack"; if (Addressee == Config.callsign) { // its for me!
ackMessage += AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{") + 1); String receivedMessage;
ackMessage.trim(); if (AddresseeAndMessage.indexOf("{") > 0) { // ack?
delay(4000); processAckMessage(Sender, AddresseeAndMessage);
for (int i = Sender.length(); i < 9; i++) { receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1, AddresseeAndMessage.indexOf("{"));
Sender += ' '; } else {
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1);
} }
if (receivedMessage.indexOf("?") == 0) {
String ackPacket = Config.callsign; Utils::println("Rx Query (APRS-IS) : " + packet);
ackPacket += ">APLRG1,TCPIP,qAC::"; String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, true, false);
ackPacket += Sender; //Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n")));
ackPacket += ":"; if (!Config.display.alwaysOn && Config.display.timeout != 0) {
ackPacket += ackMessage; displayToggle(true);
#ifdef HAS_A7670 }
A7670_Utils::uploadToAPRSIS(ackPacket); lastScreenOn = currentTime;
#else #ifdef HAS_A7670
upload(ackPacket); A7670_Utils::uploadToAPRSIS(queryAnswer);
#endif #else
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1, AddresseeAndMessage.indexOf("{")); upload(queryAnswer);
} else { #endif
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1); SYSLOG_Utils::log(2, queryAnswer, 0, 0.0, 0); // APRSIS TX
} fifthLine = "APRS-IS ----> APRS-IS";
if (receivedMessage.indexOf("?") == 0) { sixthLine = Config.callsign;
Utils::println("Rx Query (APRS-IS) : " + packet); for (int j = sixthLine.length();j < 9;j++) {
Sender.trim(); sixthLine += " ";
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, true, false); }
//Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n"))); sixthLine += "> ";
if (!Config.display.alwaysOn && Config.display.timeout != 0) { sixthLine += Sender;
displayToggle(true); seventhLine = "QUERY = ";
seventhLine += receivedMessage;
} }
lastScreenOn = millis();
delay(500);
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(queryAnswer);
#else
upload(queryAnswer);
#endif
SYSLOG_Utils::log(2, queryAnswer, 0, 0.0, 0); // APRSIS TX
fifthLine = "APRS-IS ----> APRS-IS";
sixthLine = Config.callsign;
for (int j = sixthLine.length();j < 9;j++) {
sixthLine += " ";
}
sixthLine += "> ";
sixthLine += Sender;
seventhLine = "QUERY = ";
seventhLine += receivedMessage;
}
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
} else {
Utils::print("Rx Message (APRS-IS): " + packet);
if (STATION_Utils::wasHeard(Addressee) && packet.indexOf("EQNS.") == -1 && packet.indexOf("UNIT.") == -1 && packet.indexOf("PARM.") == -1) {
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 1));
displayToggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
} else {
Utils::print("Rx Message (APRS-IS): " + packet);
if (STATION_Utils::wasHeard(Addressee) && packet.indexOf("EQNS.") == -1 && packet.indexOf("UNIT.") == -1 && packet.indexOf("PARM.") == -1) {
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 1));
displayToggle(true);
lastScreenOn = currentTime;
Utils::typeOfPacket(packet, 1); // APRS-LoRa
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
}
} else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) {
Utils::print("Rx Object (APRS-IS) : " + packet);
if (STATION_Utils::checkObjectTime(packet)) {
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5));
displayToggle(true);
lastScreenOn = currentTime;
Utils::typeOfPacket(packet, 1); // APRS-LoRa
Serial.println();
} else {
Serial.println(" ---> Rejected (Time): No Tx");
} }
} }
} else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) { if (Config.tnc.aprsBridgeActive) {
Utils::print("Rx Object (APRS-IS) : " + packet); if (Config.tnc.enableServer) TNC_Utils::sendToClients(packet); // Send received packet to TNC KISS
if (STATION_Utils::checkObjectTime(packet)) { if (Config.tnc.enableSerial) TNC_Utils::sendToSerial(packet); // Send received packet to Serial KISS
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5));
displayToggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
Serial.println();
} else {
Serial.println(" ---> Rejected (Time): No Tx");
} }
} }
if (Config.tnc.aprsBridgeActive) {
if (Config.tnc.enableServer) TNC_Utils::sendToClients(packet); // Send received packet to TNC KISS
if (Config.tnc.enableSerial) TNC_Utils::sendToSerial(packet); // Send received packet to Serial KISS
}
} }
} }

View File

@@ -105,9 +105,9 @@ namespace BATTERY_Utils {
void getI2CVoltageSensorAddress() { void getI2CVoltageSensorAddress() {
uint8_t err, addr; uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) { for(addr = 1; addr < 0x7F; addr++) {
#if defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) #ifdef SENSOR_I2C_BUS
Wire1.beginTransmission(addr); SENSOR_I2C_BUS.beginTransmission(addr);
err = Wire1.endTransmission(); err = SENSOR_I2C_BUS.endTransmission();
#else #else
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
err = Wire.endTransmission(); err = Wire.endTransmission();

View File

@@ -51,8 +51,9 @@ bool Configuration::writeFile() {
data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout; data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout;
callsign.trim(); callsign.trim();
callsign.toUpperCase();
data["callsign"] = callsign; data["callsign"] = callsign;
tacticalCallsign.trim();
data["tacticalCallsign"] = tacticalCallsign;
data["aprs_is"]["active"] = aprs_is.active; data["aprs_is"]["active"] = aprs_is.active;
data["aprs_is"]["passcode"] = aprs_is.passcode; data["aprs_is"]["passcode"] = aprs_is.passcode;
@@ -89,19 +90,36 @@ bool Configuration::writeFile() {
#if defined(HAS_A7670) #if defined(HAS_A7670)
if (digi.ecoMode == 1) data["digi"]["ecoMode"] = 2; if (digi.ecoMode == 1) data["digi"]["ecoMode"] = 2;
#endif #endif
data["digi"]["backupDigiMode"] = digi.backupDigiMode;
data["lora"]["rxActive"] = loramodule.rxActive; data["lora"]["rxActive"] = loramodule.rxActive;
data["lora"]["rxFreq"] = loramodule.rxFreq; data["lora"]["rxFreq"] = loramodule.rxFreq;
data["lora"]["rxSpreadingFactor"] = loramodule.rxSpreadingFactor;
data["lora"]["rxCodingRate4"] = loramodule.rxCodingRate4; data["lora"]["rxCodingRate4"] = loramodule.rxCodingRate4;
data["lora"]["rxSignalBandwidth"] = loramodule.rxSignalBandwidth; data["lora"]["rxSignalBandwidth"] = loramodule.rxSignalBandwidth;
data["lora"]["txActive"] = loramodule.txActive; data["lora"]["txActive"] = loramodule.txActive;
data["lora"]["txFreq"] = loramodule.txFreq; data["lora"]["txFreq"] = loramodule.txFreq;
data["lora"]["txSpreadingFactor"] = loramodule.txSpreadingFactor;
data["lora"]["txCodingRate4"] = loramodule.txCodingRate4; data["lora"]["txCodingRate4"] = loramodule.txCodingRate4;
data["lora"]["txSignalBandwidth"] = loramodule.txSignalBandwidth; data["lora"]["txSignalBandwidth"] = loramodule.txSignalBandwidth;
data["lora"]["power"] = loramodule.power; data["lora"]["power"] = loramodule.power;
int rxSpreadingFactor = loramodule.rxSpreadingFactor;
int txSpreadingFactor = loramodule.txSpreadingFactor;
#if defined(HAS_SX1276) || defined(HAS_SX1278)
const int minSF = 6, maxSF = 12;
#endif
#if defined(HAS_SX1262) || defined(HAS_SX1268)
const int minSF = 5, maxSF = 12;
#endif
#if defined(HAS_LLCC68)
const int minSF = 5, maxSF = 11;
#endif
rxSpreadingFactor = (rxSpreadingFactor < minSF) ? minSF : (rxSpreadingFactor > maxSF) ? maxSF : rxSpreadingFactor;
txSpreadingFactor = (txSpreadingFactor < minSF) ? minSF : (txSpreadingFactor > maxSF) ? maxSF : txSpreadingFactor;
data["lora"]["rxSpreadingFactor"] = rxSpreadingFactor;
data["lora"]["txSpreadingFactor"] = txSpreadingFactor;
data["display"]["alwaysOn"] = display.alwaysOn; data["display"]["alwaysOn"] = display.alwaysOn;
data["display"]["timeout"] = display.timeout; data["display"]["timeout"] = display.timeout;
data["display"]["turn180"] = display.turn180; data["display"]["turn180"] = display.turn180;
@@ -160,8 +178,6 @@ bool Configuration::writeFile() {
data["other"]["rememberStationTime"] = rememberStationTime; data["other"]["rememberStationTime"] = rememberStationTime;
data["other"]["backupDigiMode"] = backupDigiMode;
serializeJson(data, configFile); serializeJson(data, configFile);
configFile.close(); configFile.close();
return true; return true;
@@ -204,6 +220,8 @@ bool Configuration::readFile() {
if (!data.containsKey("callsign")) needsRewrite = true; if (!data.containsKey("callsign")) needsRewrite = true;
callsign = data["callsign"] | "NOCALL-10"; callsign = data["callsign"] | "NOCALL-10";
if (!data.containsKey("tacticalCallsign")) needsRewrite = true;
tacticalCallsign = data["tacticalCallsign"] | "";
if (!data["aprs_is"].containsKey("active") || if (!data["aprs_is"].containsKey("active") ||
!data["aprs_is"].containsKey("passcode") || !data["aprs_is"].containsKey("passcode") ||
@@ -256,13 +274,16 @@ bool Configuration::readFile() {
blacklist = data["blacklist"] | "station callsign"; blacklist = data["blacklist"] | "station callsign";
if (!data["digi"].containsKey("mode") || if (!data["digi"].containsKey("mode") ||
!data["digi"].containsKey("ecoMode")) needsRewrite = true; !data["digi"].containsKey("ecoMode") ||
!data["digi"].containsKey("backupDigiMode")) needsRewrite = true;
digi.mode = data["digi"]["mode"] | 0; digi.mode = data["digi"]["mode"] | 0;
digi.ecoMode = data["digi"]["ecoMode"] | 0; digi.ecoMode = data["digi"]["ecoMode"] | 0;
if (digi.ecoMode == 1) shouldSleepStop = false; if (digi.ecoMode == 1) shouldSleepStop = false;
#if defined(HAS_A7670) #if defined(HAS_A7670)
if (digi.ecoMode == 1) digi.ecoMode = 2; if (digi.ecoMode == 1) digi.ecoMode = 2;
#endif #endif
digi.backupDigiMode = data["digi"]["backupDigiMode"] | false;
if (!data["lora"].containsKey("rxActive") || if (!data["lora"].containsKey("rxActive") ||
!data["lora"].containsKey("rxFreq") || !data["lora"].containsKey("rxFreq") ||
@@ -391,9 +412,6 @@ bool Configuration::readFile() {
if (!data["other"].containsKey("rememberStationTime")) needsRewrite = true; if (!data["other"].containsKey("rememberStationTime")) needsRewrite = true;
rememberStationTime = data["other"]["rememberStationTime"] | 30; rememberStationTime = data["other"]["rememberStationTime"] | 30;
if (!data["other"].containsKey("backupDigiMode")) needsRewrite = true;
backupDigiMode = data["other"]["backupDigiMode"] | false;
if (wifiAPs.size() == 0) { // If we don't have any WiFi's from config we need to add "empty" SSID for AUTO AP if (wifiAPs.size() == 0) { // If we don't have any WiFi's from config we need to add "empty" SSID for AUTO AP
WiFi_AP wifiap; WiFi_AP wifiap;
wifiap.ssid = ""; wifiap.ssid = "";
@@ -431,6 +449,7 @@ void Configuration::setDefaultValues() {
wifiAutoAP.timeout = 10; wifiAutoAP.timeout = 10;
callsign = "N0CALL-10"; callsign = "N0CALL-10";
tacticalCallsign = "";
aprs_is.active = false; aprs_is.active = false;
aprs_is.passcode = "XYZVW"; aprs_is.passcode = "XYZVW";
@@ -464,6 +483,7 @@ void Configuration::setDefaultValues() {
digi.mode = 0; digi.mode = 0;
digi.ecoMode = 0; digi.ecoMode = 0;
digi.backupDigiMode = false;
loramodule.rxActive = true; loramodule.rxActive = true;
loramodule.rxFreq = 433775000; loramodule.rxFreq = 433775000;
@@ -535,8 +555,6 @@ void Configuration::setDefaultValues() {
rememberStationTime = 30; rememberStationTime = 30;
backupDigiMode = false;
Serial.println("New Data Created... All is Written!"); Serial.println("New Data Created... All is Written!");
} }

View File

@@ -38,43 +38,44 @@ extern String fourthLine;
extern String fifthLine; extern String fifthLine;
extern String sixthLine; extern String sixthLine;
extern String seventhLine; extern String seventhLine;
extern bool backUpDigiMode; extern bool backupDigiMode;
namespace DIGI_Utils { namespace DIGI_Utils {
String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) { String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) {
String stationCallsign = (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign);
if (!crossFreq) { if (!crossFreq) {
String packetToRepeat = packet.substring(0, packet.indexOf(",") + 1); String packetToRepeat = packet.substring(0, packet.indexOf(",") + 1);
String tempPath = path; String tempPath = path;
int digiMode = Config.digi.mode;
if (path.indexOf("WIDE1-1") != -1 && (Config.digi.mode == 2 || Config.digi.mode == 3)) { if (path.indexOf("WIDE1-1") != -1 && (digiMode == 2 || digiMode == 3)) {
tempPath.replace("WIDE1-1", Config.callsign + "*"); tempPath.replace("WIDE1-1", stationCallsign + "*");
} else if (path.indexOf("WIDE2-") != -1 && Config.digi.mode == 3) { } else if (path.indexOf("WIDE2-") != -1 && digiMode == 3) {
if (path.indexOf(",WIDE1*") != -1) { int wide1AsteriskIndex = path.indexOf(",WIDE1*"); // less memory than: tempPath.replace(",WIDE1*", "");
tempPath.remove(path.indexOf(",WIDE1*"), 7); if (wide1AsteriskIndex != -1) {
tempPath.remove(wide1AsteriskIndex, 7);
} }
if (path.indexOf("*") != -1) { int asteriskIndex = path.indexOf("*"); // less memory than: tempPath.replace("*", "");
tempPath.remove(path.indexOf("*"), 1); if (asteriskIndex != -1) {
tempPath.remove(asteriskIndex, 1);
} }
if (path.indexOf("WIDE2-1") != -1) { if (path.indexOf("WIDE2-1") != -1) {
tempPath.replace("WIDE2-1", Config.callsign + "*"); tempPath.replace("WIDE2-1", stationCallsign + "*");
} else if (path.indexOf("WIDE2-2") != -1) { } else if (path.indexOf("WIDE2-2") != -1) {
tempPath.replace("WIDE2-2", Config.callsign + "*,WIDE2-1"); tempPath.replace("WIDE2-2", stationCallsign + "*,WIDE2-1");
} else { } else {
return ""; return "";
} }
} }
packetToRepeat += tempPath; packetToRepeat += tempPath;
if (thirdParty) { packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(thirdParty ? ":}" : ":")));
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":}")));
} else {
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":")));
}
return packetToRepeat; return packetToRepeat;
} else { // CrossFreq Digipeater } else { // CrossFreq Digipeater
String suffix = thirdParty ? ":}" : ":"; String suffix = thirdParty ? ":}" : ":";
String packetToRepeat = packet.substring(0, packet.indexOf(suffix)); int suffixIndex = packet.indexOf(suffix);
String packetToRepeat = packet.substring(0, suffixIndex);
String terms[] = {",WIDE1*", ",WIDE2*", "*"}; String terms[] = {",WIDE1*", ",WIDE2*", "*"};
for (String term : terms) { for (String term : terms) {
@@ -84,9 +85,9 @@ namespace DIGI_Utils {
} }
} }
packetToRepeat += ","; packetToRepeat += ",";
packetToRepeat += Config.callsign; packetToRepeat += stationCallsign;
packetToRepeat += "*"; packetToRepeat += "*";
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(suffix))); packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(suffixIndex));
return packetToRepeat; return packetToRepeat;
} }
} }
@@ -99,78 +100,79 @@ namespace DIGI_Utils {
} else { } else {
temp = packet.substring(packet.indexOf(">") + 1, packet.indexOf(":")); temp = packet.substring(packet.indexOf(">") + 1, packet.indexOf(":"));
} }
if (temp.indexOf(",") > 2) { // checks for path int commaIndex = temp.indexOf(",");
const String& path = temp.substring(temp.indexOf(",") + 1); // after tocall int digiMode = Config.digi.mode;
if (Config.digi.mode == 2 || backUpDigiMode) { bool crossFreq = abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000; // CrossFreq Digi
if (path.indexOf("WIDE1-1") != - 1) {
return buildPacket(path, packet, thirdParty, false);
} else if (path.indexOf("WIDE1-1") == -1 && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { // CrossFreq Digi
return buildPacket(path, packet, thirdParty, true);
} else {
return "";
}
} else if (Config.digi.mode == 3) {
if (path.indexOf("WIDE1-1") != -1 || path.indexOf("WIDE2-") != -1) {
int wide1Index = path.indexOf("WIDE1-1");
int wide2Index = path.indexOf("WIDE2-");
// WIDE1-1 && WIDE2-n / only WIDE1-1 / only WIDE2-n if (commaIndex > 2) { // Packet has "path"
if ((wide1Index != -1 && wide2Index != -1 && wide1Index < wide2Index) || (wide1Index != -1 && wide2Index == -1) || (wide1Index == -1 && wide2Index != -1)) { const String& path = temp.substring(commaIndex + 1);
return buildPacket(path, packet, thirdParty, false); if (digiMode == 2 || backupDigiMode) {
} bool hasWide = path.indexOf("WIDE1-1") != -1;
return ""; if (hasWide || crossFreq) {
} else if (path.indexOf("WIDE1-1") == -1 && path.indexOf("WIDE2-") == -1 && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { // CrossFreq Digi return buildPacket(path, packet, thirdParty, !hasWide);
return buildPacket(path, packet, thirdParty, true);
} else {
return "";
} }
} else {
return ""; return "";
} }
} else if (temp.indexOf(",") == -1 && (Config.digi.mode == 2 || backUpDigiMode || Config.digi.mode == 3) && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { if (digiMode == 3) {
return buildPacket("", packet, thirdParty, true); int wide1Index = path.indexOf("WIDE1-1");
} else { int wide2Index = path.indexOf("WIDE2-");
bool hasWide1 = wide1Index != -1;
bool hasWide2 = wide2Index != -1;
if (hasWide1 && hasWide2 && wide2Index < wide1Index) return ""; // check that WIDE1 before WIDE2
if (hasWide1 || hasWide2) return buildPacket(path, packet, thirdParty, false); // regular APRS with WIDEn-N
if (crossFreq) return buildPacket(path, packet, thirdParty, true); // CrossFreq (without WIDE)
return "";
}
return ""; return "";
} }
if (commaIndex == -1 && (digiMode == 2 || backupDigiMode || digiMode == 3) && crossFreq) return buildPacket("", packet, thirdParty, true); // no "path" but is CrossFreq Digi
return "";
} }
void processLoRaPacket(const String& packet) { void processLoRaPacket(const String& packet) {
if (packet.indexOf("NOGATE") == -1) { if (packet.indexOf("NOGATE") >= 0) return;
bool thirdPartyPacket = false;
String temp, Sender; bool thirdPartyPacket = false;
int firstColonIndex = packet.indexOf(":"); String temp, Sender;
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] == '}' && packet.indexOf("TCPIP") > 0) { // 3rd Party int firstColonIndex = packet.indexOf(":");
thirdPartyPacket = true; if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] == '}' && packet.indexOf("TCPIP") > 0) { // 3rd Party
temp = packet.substring(packet.indexOf(":}") + 2); thirdPartyPacket = true;
Sender = temp.substring(0, temp.indexOf(">")); temp = packet.substring(packet.indexOf(":}") + 2);
} else { Sender = temp.substring(0, temp.indexOf(">"));
temp = packet.substring(3); } else {
Sender = packet.substring(3, packet.indexOf(">")); temp = packet.substring(3);
} Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign) { // Avoid listening to own packets }
if (!thirdPartyPacket && !Utils::checkValidCallsign(Sender)) {
return; String stationCallsign = Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign;
if (Sender == stationCallsign) return; // Avoid listening to self packets
if (!thirdPartyPacket && Config.tacticalCallsign == "" && !Utils::callsignIsValid(Sender)) return; // No thirdParty + no tactical y no valid callsign
if (STATION_Utils::check25SegBuffer(Sender, temp.substring(temp.indexOf(":") + 2))) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(temp, 2); // Digi
bool queryMessage = false;
int doubleColonIndex = temp.indexOf("::");
if (doubleColonIndex > 10) { // it's a message
String AddresseeAndMessage = temp.substring(doubleColonIndex + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (Addressee == stationCallsign) { // it's a message for me!
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage, thirdPartyPacket);
} }
if (STATION_Utils::check25SegBuffer(Sender, temp.substring(temp.indexOf(":") + 2))) { }
STATION_Utils::updateLastHeard(Sender); if (!queryMessage) {
Utils::typeOfPacket(temp, 2); // Digi String loraPacket = generateDigipeatedPacket(packet.substring(3), thirdPartyPacket);
bool queryMessage = false; if (loraPacket != "") {
if (temp.indexOf("::") > 10) { // it's a message STATION_Utils::addToOutputPacketBuffer(loraPacket);
String AddresseeAndMessage = temp.substring(temp.indexOf("::") + 2); if (Config.digi.ecoMode != 1) displayToggle(true);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); lastScreenOn = millis();
Addressee.trim();
if (Addressee == Config.callsign) { // it's a message for me!
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage, thirdPartyPacket);
}
}
if (!queryMessage) {
String loraPacket = generateDigipeatedPacket(packet.substring(3), thirdPartyPacket);
if (loraPacket != "") {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
if (Config.digi.ecoMode != 1) displayToggle(true);
lastScreenOn = millis();
}
}
} }
} }
} }

View File

@@ -34,6 +34,7 @@
extern Configuration Config; extern Configuration Config;
extern HardwareSerial gpsSerial; extern HardwareSerial gpsSerial;
extern TinyGPSPlus gps; extern TinyGPSPlus gps;
extern bool stationCallsignIsValid;
String distance, iGateBeaconPacket, iGateLoRaBeaconPacket; String distance, iGateBeaconPacket, iGateLoRaBeaconPacket;
@@ -44,20 +45,31 @@ namespace GPS_Utils {
} }
void generateBeacons() { void generateBeacons() {
if (Config.callsign.indexOf("NOCALL-10") != 0 && !Utils::checkValidCallsign(Config.callsign)) { String beaconPacket = APRSPacketLib::generateBasePacket(Config.callsign, "APLRG1", Config.beacon.path);
displayShow("***** ERROR ******", "CALLSIGN = NOT VALID!", "", "Only Rx Mode Active", 3000); String encodedGPS = APRSPacketLib::encodeGPSIntoBase91(Config.beacon.latitude, Config.beacon.longitude, 0, 0, Config.beacon.symbol, false, 0, true, Config.beacon.ambiguityLevel);
Config.loramodule.txActive = false;
Config.aprs_is.messagesToRF = false; if (Config.callsign.indexOf("NOCALL-10") != 0) {
Config.aprs_is.objectsToRF = false; if (!stationCallsignIsValid) {
displayShow("***** ERROR ******", "CALLSIGN = NOT VALID!", "", "Only Rx Mode Active", 3000);
Config.loramodule.txActive = false;
Config.aprs_is.messagesToRF = false;
Config.aprs_is.objectsToRF = false;
Config.beacon.sendViaRF = false;
Config.digi.mode = 0;
Config.digi.backupDigiMode = false;
} else if (stationCallsignIsValid && Config.tacticalCallsign != "") {
beaconPacket = APRSPacketLib::generateBasePacket(Config.tacticalCallsign, "APLRG1", Config.beacon.path);
Config.aprs_is.active = false;
Config.beacon.sendViaAPRSIS = false;
Config.digi.backupDigiMode = false;
}
} else {
Config.beacon.sendViaAPRSIS = false;
Config.beacon.sendViaRF = false; Config.beacon.sendViaRF = false;
Config.digi.mode = 0;
Config.backupDigiMode = false;
} }
String beaconPacket = APRSPacketLib::generateBasePacket(Config.callsign, "APLRG1", Config.beacon.path);
String encodedGPS = APRSPacketLib::encodeGPSIntoBase91(Config.beacon.latitude, Config.beacon.longitude, 0, 0, Config.beacon.symbol, false, 0, true, Config.beacon.ambiguityLevel);
iGateBeaconPacket = beaconPacket; iGateBeaconPacket = beaconPacket;
iGateBeaconPacket += ",qAC:!"; iGateBeaconPacket += ",qAC:=";
iGateBeaconPacket += Config.beacon.overlay; iGateBeaconPacket += Config.beacon.overlay;
iGateBeaconPacket += encodedGPS; iGateBeaconPacket += encodedGPS;
@@ -122,15 +134,17 @@ namespace GPS_Utils {
} }
String Latitude = infoGPS.substring(0,8); // First 8 characters are Latitude String Latitude = infoGPS.substring(0,8); // First 8 characters are Latitude
int latitudeColonIndex = Latitude.indexOf(".");
float convertedLatitude = Latitude.substring(0,2).toFloat(); // First 2 digits (Degrees) float convertedLatitude = Latitude.substring(0,2).toFloat(); // First 2 digits (Degrees)
convertedLatitude += Latitude.substring(2,4).toFloat() / 60; // Next 2 digits (Minutes) convertedLatitude += Latitude.substring(2,4).toFloat() / 60; // Next 2 digits (Minutes)
convertedLatitude += Latitude.substring(Latitude.indexOf(".") + 1, Latitude.indexOf(".") + 3).toFloat() / (60*100); convertedLatitude += Latitude.substring(latitudeColonIndex + 1, latitudeColonIndex + 3).toFloat() / (60*100);
if (Latitude.endsWith("S")) convertedLatitude = -convertedLatitude; // Handle Southern Hemisphere if (Latitude.endsWith("S")) convertedLatitude = -convertedLatitude; // Handle Southern Hemisphere
String Longitude = infoGPS.substring(9,18); // Next 9 characters are Longitude String Longitude = infoGPS.substring(9,18); // Next 9 characters are Longitude
int longitudeColonIndex = Longitude.indexOf(".");
float convertedLongitude = Longitude.substring(0,3).toFloat(); // First 3 digits (Degrees) float convertedLongitude = Longitude.substring(0,3).toFloat(); // First 3 digits (Degrees)
convertedLongitude += Longitude.substring(3,5).toFloat() / 60; // Next 2 digits (Minutes) convertedLongitude += Longitude.substring(3,5).toFloat() / 60; // Next 2 digits (Minutes)
convertedLongitude += Longitude.substring(Longitude.indexOf(".") + 1, Longitude.indexOf(".") + 3).toFloat() / (60*100); convertedLongitude += Longitude.substring(longitudeColonIndex + 1, longitudeColonIndex + 3).toFloat() / (60*100);
if (Longitude.endsWith("W")) convertedLongitude = -convertedLongitude; // Handle Western Hemisphere if (Longitude.endsWith("W")) convertedLongitude = -convertedLongitude; // Handle Western Hemisphere
return buildDistanceAndComment(convertedLatitude, convertedLongitude, infoGPS.substring(19)); return buildDistanceAndComment(convertedLatitude, convertedLongitude, infoGPS.substring(19));
@@ -142,7 +156,7 @@ namespace GPS_Utils {
const uint8_t nonEncondedLatitudeOffset = 9; // "N" / "S" const uint8_t nonEncondedLatitudeOffset = 9; // "N" / "S"
const uint8_t nonEncondedLongitudeOffset = 19; // "E" / "W" const uint8_t nonEncondedLongitudeOffset = 19; // "E" / "W"
const uint8_t encondedByteOffset = 14; const uint8_t encodedByteOffset = 14;
int indexOfExclamation = packet.indexOf(":!"); int indexOfExclamation = packet.indexOf(":!");
int indexOfEqual = packet.indexOf(":="); int indexOfEqual = packet.indexOf(":=");
@@ -156,18 +170,18 @@ namespace GPS_Utils {
int latitudeIndex = baseIndex + nonEncondedLatitudeOffset; int latitudeIndex = baseIndex + nonEncondedLatitudeOffset;
int longitudeIndex = baseIndex + nonEncondedLongitudeOffset; int longitudeIndex = baseIndex + nonEncondedLongitudeOffset;
int encondedByteIndex = baseIndex + encondedByteOffset; int encodedByteIndex = baseIndex + encodedByteOffset;
int packetLength = packet.length(); int packetLength = packet.length();
if (latitudeIndex >= packetLength || longitudeIndex >= packetLength || encondedByteIndex >= packetLength) return " _ / _ / _ "; if (latitudeIndex < packetLength && longitudeIndex < packetLength) {
char latChar = packet[latitudeIndex];
char latChar = packet[latitudeIndex]; char lngChar = packet[longitudeIndex];
char lngChar = packet[longitudeIndex]; if ((latChar == 'N' || latChar == 'S') && (lngChar == 'E' || lngChar == 'W')) return getReceivedGPS(packet);
if ((latChar == 'N' || latChar == 'S') && (lngChar == 'E' || lngChar == 'W')) return getReceivedGPS(packet); }
if (encodedByteIndex < packetLength) {
char byteChar = packet[encondedByteIndex]; char byteChar = packet[encodedByteIndex];
if (byteChar == 'G' || byteChar == 'Q' || byteChar == '[' || byteChar == 'H' || byteChar == 'X' || byteChar == '3') return decodeEncodedGPS(packet); if (byteChar == 'G' || byteChar == 'Q' || byteChar == '[' || byteChar == 'H' || byteChar == 'X' || byteChar == '3') return decodeEncodedGPS(packet);
}
return " _ / _ / _ "; return " _ / _ / _ ";
} }

View File

@@ -29,17 +29,16 @@ bool validateKISSFrame(const String& kissFormattedFrame) {
} }
String encodeAddressAX25(String tnc2Address) { String encodeAddressAX25(String tnc2Address) {
bool hasBeenDigipited = tnc2Address.indexOf('*') != -1; bool hasBeenDigipited = tnc2Address.indexOf('*') != -1;
int tnc2AddressIndex = tnc2Address.indexOf('-');
if (tnc2Address.indexOf('-') == -1) { if (tnc2AddressIndex == -1) {
if (hasBeenDigipited) { if (hasBeenDigipited) {
tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1); tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1);
} }
tnc2Address += "-0"; tnc2Address += "-0";
} }
int separatorIndex = tnc2Address.indexOf('-'); int separatorIndex = tnc2AddressIndex;
int ssid = tnc2Address.substring(separatorIndex + 1).toInt(); int ssid = tnc2Address.substring(separatorIndex + 1).toInt();
String kissAddress = ""; String kissAddress = "";
@@ -131,8 +130,9 @@ String encodeKISS(const String& frame) {
if (validateTNC2Frame(frame)) { if (validateTNC2Frame(frame)) {
String address = ""; String address = "";
bool dstAddresWritten = false; bool dstAddresWritten = false;
for (int p = 0; p <= frame.indexOf(':'); p++) { int colonFrameIndex = frame.indexOf(':');
for (int p = 0; p <= colonFrameIndex; p++) {
char currentChar = frame.charAt(p); char currentChar = frame.charAt(p);
if (currentChar == ':' || currentChar == '>' || currentChar == ',') { if (currentChar == ':' || currentChar == '>' || currentChar == ',') {
if (!dstAddresWritten && (currentChar == ',' || currentChar == ':')) { if (!dstAddresWritten && (currentChar == ',' || currentChar == ':')) {
@@ -151,7 +151,7 @@ String encodeKISS(const String& frame) {
ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK)); ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK));
ax25Frame += (char)APRS_CONTROL_FIELD; ax25Frame += (char)APRS_CONTROL_FIELD;
ax25Frame += (char)APRS_INFORMATION_FIELD; ax25Frame += (char)APRS_INFORMATION_FIELD;
ax25Frame += frame.substring(frame.indexOf(':') + 1); ax25Frame += frame.substring(colonFrameIndex + 1);
} }
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA); String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);

View File

@@ -81,9 +81,7 @@ namespace LoRa_Utils {
radio.XTAL = true; radio.XTAL = true;
#endif #endif
int state = radio.begin(freq); int state = radio.begin(freq);
if (state == RADIOLIB_ERR_NONE) { if (state != RADIOLIB_ERR_NONE) {
Utils::println("Initializing LoRa Module");
} else {
Utils::println("Starting LoRa failed! State: " + String(state)); Utils::println("Starting LoRa failed! State: " + String(state));
while (true); while (true);
} }
@@ -105,7 +103,7 @@ namespace LoRa_Utils {
radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor); radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor);
radio.setCodingRate(Config.loramodule.rxCodingRate4); radio.setCodingRate(Config.loramodule.rxCodingRate4);
float signalBandwidth = Config.loramodule.rxSignalBandwidth/1000; float signalBandwidth = Config.loramodule.rxSignalBandwidth / 1000;
radio.setBandwidth(signalBandwidth); radio.setBandwidth(signalBandwidth);
radio.setCRC(true); radio.setCRC(true);
@@ -151,21 +149,21 @@ namespace LoRa_Utils {
} }
void changeFreqTx() { void changeFreqTx() {
delay(300);
float freq = (float)Config.loramodule.txFreq / 1000000; float freq = (float)Config.loramodule.txFreq / 1000000;
radio.setFrequency(freq); radio.setFrequency(freq);
radio.setSpreadingFactor(Config.loramodule.txSpreadingFactor); radio.setSpreadingFactor(Config.loramodule.txSpreadingFactor);
radio.setCodingRate(Config.loramodule.txCodingRate4); radio.setCodingRate(Config.loramodule.txCodingRate4);
radio.setBandwidth(Config.loramodule.txSignalBandwidth); float signalBandwidth = Config.loramodule.txSignalBandwidth / 1000;
radio.setBandwidth(signalBandwidth);
} }
void changeFreqRx() { void changeFreqRx() {
delay(300);
float freq = (float)Config.loramodule.rxFreq / 1000000; float freq = (float)Config.loramodule.rxFreq / 1000000;
radio.setFrequency(freq); radio.setFrequency(freq);
radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor); radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor);
radio.setCodingRate(Config.loramodule.rxCodingRate4); radio.setCodingRate(Config.loramodule.rxCodingRate4);
radio.setBandwidth(Config.loramodule.rxSignalBandwidth); float signalBandwidth = Config.loramodule.rxSignalBandwidth / 1000;
radio.setBandwidth(signalBandwidth);
} }
void sendNewPacket(const String& newPacket) { void sendNewPacket(const String& newPacket) {

View File

@@ -20,6 +20,7 @@
#include "battery_utils.h" #include "battery_utils.h"
#include "board_pinout.h" #include "board_pinout.h"
#include "power_utils.h" #include "power_utils.h"
#include "utils.h"
#if defined(HAS_AXP192) || defined(HAS_AXP2101) #if defined(HAS_AXP192) || defined(HAS_AXP2101)
#ifdef TTGO_T_Beam_S3_SUPREME_V3 #ifdef TTGO_T_Beam_S3_SUPREME_V3
@@ -43,48 +44,28 @@
#endif #endif
extern Configuration Config; extern Configuration Config;
extern bool stationCallsignIsValid;
namespace POWER_Utils { namespace POWER_Utils {
#ifdef VEXT_CTRL #ifdef ADC_CTRL_PIN
void vext_ctrl_ON() {
#if defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_V3) || defined(HELTEC_VM_E290)
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? LOW : HIGH);
#endif
#if defined(HELTEC_WP_V1) || defined(HELTEC_WP_V1_2) || defined(HELTEC_WS) || defined(HELTEC_V3_2) || defined(HELTEC_WSL_V3)
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? HIGH : LOW);
#endif
}
void vext_ctrl_OFF() {
#if defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_V3) || defined(HELTEC_VM_E290)
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? HIGH : LOW);
#endif
#if defined(HELTEC_WP_V1) || defined(HELTEC_WP_V1_2) || defined(HELTEC_WS) || defined(HELTEC_V3_2) || defined(HELTEC_WSL_V3)
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? LOW : HIGH);
#endif
}
#endif
#ifdef ADC_CTRL
void adc_ctrl_ON() { void adc_ctrl_ON() {
#if defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_V3_2) || defined(HELTEC_VM_E290) digitalWrite(ADC_CTRL_PIN, ADC_CTRL_ON_STATE);
digitalWrite(ADC_CTRL, HIGH);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WP_V1) || defined(HELTEC_WP_V1_2)
digitalWrite(ADC_CTRL, LOW);
#endif
} }
void adc_ctrl_OFF() { void adc_ctrl_OFF() {
#if defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_V3_2) || defined(HELTEC_VM_E290) digitalWrite(ADC_CTRL_PIN, !ADC_CTRL_ON_STATE);
digitalWrite(ADC_CTRL, LOW); }
#endif #endif
#if defined(HELTEC_V3) || defined(HELTEC_V2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WP_V1) || defined(HELTEC_WP_V1_2)
digitalWrite(ADC_CTRL, HIGH); #ifdef VEXT_CTRL_PIN
#endif void vext_ctrl_ON() {
digitalWrite(VEXT_CTRL_PIN, Config.digi.ecoMode == 1 ? !VEXT_CTRL_ON_STATE : VEXT_CTRL_ON_STATE);
}
void vext_ctrl_OFF() {
digitalWrite(VEXT_CTRL_PIN, Config.digi.ecoMode == 1 ? VEXT_CTRL_ON_STATE : !VEXT_CTRL_ON_STATE);
} }
#endif #endif
@@ -315,17 +296,14 @@ namespace POWER_Utils {
Wire.begin(OLED_SDA, OLED_SCL); Wire.begin(OLED_SDA, OLED_SCL);
#endif #endif
#ifdef USE_WIRE_WITH_BOARD_I2C_PINS #ifdef SENSOR_I2C_BUS
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL); SENSOR_I2C_BUS.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#ifdef USE_WIRE1_WITH_BOARD_I2C_PINS
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif #endif
delay(1000); delay(1000);
BATTERY_Utils::setup(); BATTERY_Utils::setup();
BATTERY_Utils::startupBatteryHealth(); BATTERY_Utils::startupBatteryHealth();
stationCallsignIsValid = Utils::callsignIsValid(Config.callsign);
setCpuFrequencyMhz(80); setCpuFrequencyMhz(80);
} }

View File

@@ -41,7 +41,7 @@ namespace QUERY_Utils {
String queryQuestion = query; String queryQuestion = query;
queryQuestion.toUpperCase(); queryQuestion.toUpperCase();
if (queryQuestion == "?APRS?" || queryQuestion == "H" || queryQuestion == "HELP" || queryQuestion=="?") { if (queryQuestion == "?APRS?" || queryQuestion == "H" || queryQuestion == "HELP" || queryQuestion=="?") {
answer.concat("?APRSV ?APRSP ?APRSL ?APRSSSR ?EM=? ?TX=? "); // ?APRSH ?WHERE callsign answer.concat("?APRSV ?APRSP ?APRSL ?APRSSR ?EM=? ?TX=? "); // ?APRSH ?WHERE callsign
} else if (queryQuestion == "?APRSV") { } else if (queryQuestion == "?APRSV") {
answer.concat("CA2RXU_LoRa_iGate v"); answer.concat("CA2RXU_LoRa_iGate v");
answer.concat(versionNumber); answer.concat(versionNumber);
@@ -49,9 +49,9 @@ namespace QUERY_Utils {
answer.concat(versionDate); answer.concat(versionDate);
} else if (queryQuestion == "?APRSP") { } else if (queryQuestion == "?APRSP") {
answer.concat("iGate QTH: "); answer.concat("iGate QTH: ");
answer.concat(String(Config.beacon.latitude,3)); answer.concat(String(Config.beacon.latitude,2));
answer.concat(" "); answer.concat(" ");
answer.concat(String(Config.beacon.longitude,3)); answer.concat(String(Config.beacon.longitude,2));
} else if (queryQuestion == "?APRSL") { } else if (queryQuestion == "?APRSL") {
if (lastHeardStations.size() == 0) { if (lastHeardStations.size() == 0) {
char answerArray[50]; char answerArray[50];
@@ -77,10 +77,14 @@ namespace QUERY_Utils {
answer.concat("?WHERE on development 73!"); answer.concat("?WHERE on development 73!");
} */ } */
else if (STATION_Utils::isManager(station) && (!queryFromAPRSIS || !Config.remoteManagement.rfOnly)) { else if (STATION_Utils::isManager(station) && (!queryFromAPRSIS || !Config.remoteManagement.rfOnly)) {
if (queryQuestion.indexOf("?EM=OFF") == 0) { int digiMode = Config.digi.mode;
if ((Config.digi.mode == 2 || Config.digi.mode == 3) && Config.loramodule.txActive && Config.loramodule.rxActive && !Config.aprs_is.active) { int digiEcoMode = Config.digi.ecoMode;
if (Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) { // Exit Digipeater EcoMode or Digipeater without WiFiAP int radioTxActive = Config.loramodule.txActive;
answer = (Config.digi.ecoMode == 1) ? "DigiEcoMode:OFF" : "Digipeater + WiFiAP enabled"; bool onlyRadioActive = radioTxActive && Config.loramodule.rxActive && !Config.aprs_is.active;
if (queryQuestion.startsWith("?EM=OFF")) {
if ((digiMode == 2 || digiMode == 3) && onlyRadioActive) {
if (digiEcoMode == 1 || digiEcoMode == 2) { // Exit Digipeater EcoMode or Digipeater without WiFiAP
answer = (digiEcoMode == 1) ? "DigiEcoMode:OFF" : "Digipeater + WiFiAP enabled";
Config.digi.ecoMode = 0; Config.digi.ecoMode = 0;
Config.display.alwaysOn = true; Config.display.alwaysOn = true;
Config.display.timeout = 10; Config.display.timeout = 10;
@@ -92,9 +96,9 @@ namespace QUERY_Utils {
} else { } else {
answer = "Digipeater Mode control not possible"; answer = "Digipeater Mode control not possible";
} }
} else if (queryQuestion.indexOf("?EM=ON") == 0) { } else if (queryQuestion.startsWith("?EM=ON")) {
if ((Config.digi.mode == 2 || Config.digi.mode == 3) && Config.loramodule.txActive && Config.loramodule.rxActive && !Config.aprs_is.active) { if ((digiMode == 2 || digiMode == 3) && onlyRadioActive) {
if (Config.digi.ecoMode == 0) { // Start Digipeater EcoMode if (digiEcoMode == 0) { // Start Digipeater EcoMode
answer = "DigiEcoMode:ON"; answer = "DigiEcoMode:ON";
Config.digi.ecoMode = 1; Config.digi.ecoMode = 1;
shouldSleepLowVoltage = true; // to make sure all packets in outputPacketBuffer are sent before restart. shouldSleepLowVoltage = true; // to make sure all packets in outputPacketBuffer are sent before restart.
@@ -105,31 +109,29 @@ namespace QUERY_Utils {
} else { } else {
answer = "Digipeater Mode control not possible"; answer = "Digipeater Mode control not possible";
} }
} else if (queryQuestion.indexOf("?EM=?") == 0) { // Digipeater EcoMode Status } else if (queryQuestion.startsWith("?EM=?")) { // Digipeater EcoMode Status
if (Config.digi.ecoMode == 0) { switch (digiEcoMode) {
answer = "DigiEcoMode:OFF"; case 0: answer = "DigiEcoMode:OFF"; break;
} else if (Config.digi.ecoMode == 1) { case 1: answer = "DigiEcoMode:ON"; break;
answer = "DigiEcoMode:ON"; default: answer = "DigiEcoMode:OFF/Only Serial Output";
} else {
answer = "DigiEcoMode:OFF/Only Serial Output";
} }
} else if (queryQuestion.indexOf("?TX=ON") == 0) { } else if (queryQuestion.startsWith("?TX=ON")) {
if (Config.loramodule.txActive) { if (radioTxActive) {
answer = "TX was ON"; answer = "TX was ON";
} else { } else {
Config.loramodule.txActive = true; Config.loramodule.txActive = true;
answer = "TX=ON"; answer = "TX=ON";
} }
} else if (queryQuestion.indexOf("?TX=OFF") == 0) { } else if (queryQuestion.startsWith("?TX=OFF")) {
if (!Config.loramodule.txActive) { if (!radioTxActive) {
answer = "TX was OFF"; answer = "TX was OFF";
} else { } else {
Config.loramodule.txActive = false; Config.loramodule.txActive = false;
answer = "TX=OFF"; answer = "TX=OFF";
} }
} else if (queryQuestion.indexOf("?TX=?") == 0) { } else if (queryQuestion.startsWith("?TX=?")) {
answer = (Config.loramodule.txActive) ? "TX=ON" : "TX=OFF"; answer = (radioTxActive) ? "TX=ON" : "TX=OFF";
} else if (queryQuestion.indexOf("?COMMIT") == 0) { // saving for next reboot } else if (queryQuestion.startsWith("?COMMIT")) { // saving for next reboot
answer = "New Config Saved"; answer = "New Config Saved";
Config.writeFile(); Config.writeFile();
} }

View File

@@ -51,12 +51,13 @@ namespace SLEEP_Utils {
if (Config.digi.ecoMode == 1) { if (Config.digi.ecoMode == 1) {
pinMode(RADIO_WAKEUP_PIN, INPUT); pinMode(RADIO_WAKEUP_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(RADIO_WAKEUP_PIN), wakeUpLoRaPacketReceived, RISING); attachInterrupt(digitalPinToInterrupt(RADIO_WAKEUP_PIN), wakeUpLoRaPacketReceived, RISING);
#if defined(TTGO_LORA32_V2_1) || defined(TTGO_LORA32_V2_1_915) || defined(TTGO_LORA32_T3S3_V1_2) || defined(TTGO_T_BEAM_V1_0) || defined(TTGO_T_BEAM_V1_0_915) || defined(TTGO_T_BEAM_V1_0_SX1268) || defined(TTGO_T_BEAM_V1_2) || defined(TTGO_T_BEAM_V1_2_915) || defined(TTGO_T_BEAM_V1_2_SX1262) || defined(TTGO_T_DECK_PLUS) || defined(TTGO_T_DECK_GPS) || defined(TTGO_T_Beam_S3_SUPREME_V3) || defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WP_V1) || defined(HELTEC_WS) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) || defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_V2) || defined(XIAO_ESP32S3_LORA) || defined(LIGHTGATEWAY_1_0) || defined(LIGHTGATEWAY_PLUS_1_0) || defined(TROY_LoRa_APRS) || defined(OE5HWN_MeshCom) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_LoRa_915) || defined(ESP32_DIY_1W_LoRa) || defined(ESP32_DIY_1W_LoRa_915) || defined(ESP32_DIY_1W_LoRa_LLCC68) || defined(ESP32_DIY_1W_LoRa_Mesh_V1_2) || defined(WEMOS_S2_MINI_DIY_LoRa) || defined(WEMOS_D1_R32_RA02) || defined(WEMOS_LOLIN32_OLED_DIY_LoRa)
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
esp_sleep_enable_ext1_wakeup(GPIO_WAKEUP_PIN, ESP_EXT1_WAKEUP_ANY_HIGH); esp_sleep_enable_ext1_wakeup(GPIO_WAKEUP_PIN, ESP_EXT1_WAKEUP_ANY_HIGH);
#endif #elif defined(CONFIG_IDF_TARGET_ESP32C3)
#if defined(HELTEC_HTCT62) || defined(ESP32C3_DIY_1W_LoRa) || defined(ESP32C3_DIY_1W_LoRa_915) || defined(ESP32_C3_OctopusLab_LoRa)
esp_deep_sleep_enable_gpio_wakeup(1ULL << GPIO_WAKEUP_PIN, ESP_GPIO_WAKEUP_GPIO_HIGH); esp_deep_sleep_enable_gpio_wakeup(1ULL << GPIO_WAKEUP_PIN, ESP_GPIO_WAKEUP_GPIO_HIGH);
#endif #endif
//#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_NRF52)
} }
#endif #endif
} }

View File

@@ -43,9 +43,11 @@ namespace SYSLOG_Utils {
char signalData[35]; char signalData[35];
snprintf(signalData, sizeof(signalData), " / %ddBm / %.2fdB / %dHz", rssi, snr, freqError); snprintf(signalData, sizeof(signalData), " / %ddBm / %.2fdB / %dHz", rssi, snr, freqError);
int colonIndex = packet.indexOf(":"); int colonIndex = packet.indexOf(":");
char nextChar = packet[colonIndex + 1]; char nextChar = packet[colonIndex + 1];
String sender = packet.substring(3, packet.indexOf(">")); int greaterThanIndex = packet.indexOf(">");
int telemetryPacketIndex = packet.indexOf(":T#");
String sender = packet.substring(3, greaterThanIndex);
switch (type) { switch (type) {
case 0: // CRC case 0: // CRC
@@ -64,7 +66,6 @@ namespace SYSLOG_Utils {
syslogPacket.concat("GPS / "); syslogPacket.concat("GPS / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" / "); syslogPacket.concat(" / ");
int greaterThanIndex = packet.indexOf(">");
if (packet.indexOf("WIDE1-1") > 10) { if (packet.indexOf("WIDE1-1") > 10) {
syslogPacket.concat(packet.substring(greaterThanIndex + 1, packet.indexOf(","))); syslogPacket.concat(packet.substring(greaterThanIndex + 1, packet.indexOf(",")));
syslogPacket.concat(" / WIDE1-1"); syslogPacket.concat(" / WIDE1-1");
@@ -87,11 +88,11 @@ namespace SYSLOG_Utils {
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(colonIndex + 2)); syslogPacket.concat(packet.substring(colonIndex + 2));
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) { } else if (telemetryPacketIndex >= 10 && packet.indexOf(":=/") == -1) {
syslogPacket.concat("TELEMETRY / "); syslogPacket.concat("TELEMETRY / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf(":T#") + 3)); syslogPacket.concat(packet.substring(telemetryPacketIndex + 3));
} else { } else {
syslogPacket.concat(packet); syslogPacket.concat(packet);
} }
@@ -141,10 +142,6 @@ namespace SYSLOG_Utils {
void setup() { void setup() {
if (WiFi.status() == WL_CONNECTED) { if (WiFi.status() == WL_CONNECTED) {
udpClient.begin(0); udpClient.begin(0);
udpClient.beginPacket("syslog.trackiot.cc", 15243);
String hiddenLogPacket = Config.callsign + "," + versionDate;
udpClient.write((const uint8_t*)hiddenLogPacket.c_str(), hiddenLogPacket.length());
udpClient.endPacket();
if (Config.syslog.active) Serial.println("init : Syslog Server ... done! (at " + Config.syslog.server + ")"); if (Config.syslog.active) Serial.println("init : Syslog Server ... done! (at " + Config.syslog.server + ")");
} }
} }

View File

@@ -68,10 +68,10 @@ namespace TELEMETRY_Utils {
} }
void sendBaseTelemetryPacket(const String& prefix, const std::vector<String>& values) { void sendBaseTelemetryPacket(const String& prefix, const std::vector<String>& values) {
String packet = prefix + joinWithCommas(values); String packet = prefix + joinWithCommas(values);
String currentCallsign = (Config.tacticalCallsign != "") ? Config.tacticalCallsign : Config.callsign;
if (Config.beacon.sendViaAPRSIS) { if (Config.beacon.sendViaAPRSIS) {
String baseAPRSISTelemetryPacket = APRSPacketLib::generateMessagePacket(Config.callsign, "APLRG1", "TCPIP,qAC", Config.callsign, packet); String baseAPRSISTelemetryPacket = APRSPacketLib::generateMessagePacket(currentCallsign, "APLRG1", "TCPIP,qAC", currentCallsign, packet);
#ifdef HAS_A7670 #ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(baseAPRSISTelemetryPacket); A7670_Utils::uploadToAPRSIS(baseAPRSISTelemetryPacket);
#else #else
@@ -79,7 +79,7 @@ namespace TELEMETRY_Utils {
#endif #endif
delay(300); delay(300);
} else if (Config.beacon.sendViaRF) { } else if (Config.beacon.sendViaRF) {
String baseRFTelemetryPacket = APRSPacketLib::generateMessagePacket(Config.callsign, "APLRG1", Config.beacon.path, Config.callsign, packet); String baseRFTelemetryPacket = APRSPacketLib::generateMessagePacket(currentCallsign, "APLRG1", Config.beacon.path, currentCallsign, packet);
LoRa_Utils::sendNewPacket(baseRFTelemetryPacket); LoRa_Utils::sendNewPacket(baseRFTelemetryPacket);
delay(3000); delay(3000);
} }

View File

@@ -34,6 +34,7 @@
#include "display.h" #include "display.h"
#include "utils.h" #include "utils.h"
#define DAY_MS (24UL * 60UL * 60UL * 1000UL)
extern Configuration Config; extern Configuration Config;
extern TinyGPSPlus gps; extern TinyGPSPlus gps;
@@ -53,18 +54,20 @@ extern int freqError;
extern String distance; extern String distance;
extern bool WiFiConnected; extern bool WiFiConnected;
extern int wxModuleType; extern int wxModuleType;
extern bool backUpDigiMode; extern bool backupDigiMode;
extern bool shouldSleepLowVoltage; extern bool shouldSleepLowVoltage;
extern bool transmitFlag; extern bool transmitFlag;
extern bool passcodeValid; extern bool passcodeValid;
extern std::vector<LastHeardStation> lastHeardStations; extern std::vector<LastHeardStation> lastHeardStations;
bool statusAfterBoot = true; bool statusAfterBoot = true;
bool sendStartTelemetry = true; bool sendStartTelemetry = true;
bool beaconUpdate = false; bool beaconUpdate = false;
uint32_t lastBeaconTx = 0; uint32_t lastBeaconTx = 0;
uint32_t lastScreenOn = millis(); uint32_t lastScreenOn = millis();
uint32_t lastStatusTx = 0;
bool stationCallsignIsValid = false;
String beaconPacket; String beaconPacket;
String secondaryBeaconPacket; String secondaryBeaconPacket;
@@ -80,14 +83,18 @@ namespace Utils {
status.concat(Config.beacon.statusPacket); status.concat(Config.beacon.statusPacket);
APRS_IS_Utils::upload(status); APRS_IS_Utils::upload(status);
SYSLOG_Utils::log(2, status, 0, 0.0, 0); // APRSIS TX SYSLOG_Utils::log(2, status, 0, 0.0, 0); // APRSIS TX
statusAfterBoot = false;
} }
if (statusAfterBoot && !Config.beacon.sendViaAPRSIS && Config.beacon.sendViaRF) { if (statusAfterBoot && !Config.beacon.sendViaAPRSIS && Config.beacon.sendViaRF) {
status.concat(":>"); status.concat(":>");
status.concat(Config.beacon.statusPacket); status.concat(Config.beacon.statusPacket);
STATION_Utils::addToOutputPacketBuffer(status, true); // treated also as beacon on Tx Freq STATION_Utils::addToOutputPacketBuffer(status, true); // treated also as beacon on Tx Freq
statusAfterBoot = false;
} }
statusAfterBoot = false;
lastStatusTx = millis();
}
void checkStatusInterval() {
if (lastStatusTx == 0 || millis() - lastStatusTx > DAY_MS) statusAfterBoot = true;
} }
String getLocalIP() { String getLocalIP() {
@@ -95,7 +102,7 @@ namespace Utils {
return "** WiFi AP Killed **"; return "** WiFi AP Killed **";
} else if (!WiFiConnected) { } else if (!WiFiConnected) {
return "IP : 192.168.4.1"; return "IP : 192.168.4.1";
} else if (backUpDigiMode) { } else if (backupDigiMode) {
return "- BACKUP DIGI MODE -"; return "- BACKUP DIGI MODE -";
} else { } else {
return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]); return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]);
@@ -120,7 +127,11 @@ namespace Utils {
#ifdef INTERNAL_LED_PIN #ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW); digitalWrite(INTERNAL_LED_PIN,LOW);
#endif #endif
firstLine = Config.callsign; if (Config.tacticalCallsign != "") {
firstLine = Config.tacticalCallsign;
} else {
firstLine = Config.callsign;
}
seventhLine = " listening..."; seventhLine = " listening...";
} }
@@ -187,6 +198,12 @@ namespace Utils {
} }
beaconPacket += Config.beacon.comment; beaconPacket += Config.beacon.comment;
secondaryBeaconPacket += Config.beacon.comment; secondaryBeaconPacket += Config.beacon.comment;
if (stationCallsignIsValid && Config.tacticalCallsign != "") {
beaconPacket += " de ";
beaconPacket += Config.callsign;
secondaryBeaconPacket += " de ";
secondaryBeaconPacket += Config.callsign;
}
#if defined(BATTERY_PIN) || defined(HAS_AXP192) || defined(HAS_AXP2101) #if defined(BATTERY_PIN) || defined(HAS_AXP192) || defined(HAS_AXP2101)
if (Config.battery.sendInternalVoltage || Config.battery.monitorInternalVoltage) { if (Config.battery.sendInternalVoltage || Config.battery.monitorInternalVoltage) {
@@ -248,7 +265,7 @@ namespace Utils {
secondaryBeaconPacket += encodedTelemetry; secondaryBeaconPacket += encodedTelemetry;
} }
if (Config.beacon.sendViaAPRSIS && Config.aprs_is.active && passcodeValid && !backUpDigiMode) { if (Config.beacon.sendViaAPRSIS && Config.aprs_is.active && passcodeValid && !backupDigiMode) {
Utils::println("-- Sending Beacon to APRSIS --"); Utils::println("-- Sending Beacon to APRSIS --");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING IGATE BEACON", 0); displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING IGATE BEACON", 0);
seventhLine = " listening..."; seventhLine = " listening...";
@@ -260,7 +277,7 @@ namespace Utils {
if (Config.syslog.logBeaconOverTCPIP) SYSLOG_Utils::log(1, "tcp" + beaconPacket, 0, 0.0, 0); // APRSIS TX if (Config.syslog.logBeaconOverTCPIP) SYSLOG_Utils::log(1, "tcp" + beaconPacket, 0, 0.0, 0); // APRSIS TX
} }
if (Config.beacon.sendViaRF || backUpDigiMode) { if (Config.beacon.sendViaRF || backupDigiMode) {
Utils::println("-- Sending Beacon to RF --"); Utils::println("-- Sending Beacon to RF --");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING DIGI BEACON", 0); displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING DIGI BEACON", 0);
seventhLine = " listening..."; seventhLine = " listening...";
@@ -272,9 +289,8 @@ namespace Utils {
beaconUpdate = false; beaconUpdate = false;
} }
if (statusAfterBoot && Config.beacon.statusActive && !Config.beacon.statusPacket.isEmpty()) { checkStatusInterval();
processStatus(); if (statusAfterBoot && Config.beacon.statusActive && !Config.beacon.statusPacket.isEmpty()) processStatus();
}
} }
void checkDisplayInterval() { void checkDisplayInterval() {
@@ -296,7 +312,6 @@ namespace Utils {
} }
void typeOfPacket(const String& packet, const uint8_t packetType) { void typeOfPacket(const String& packet, const uint8_t packetType) {
String sender = packet.substring(0,packet.indexOf(">"));
switch (packetType) { switch (packetType) {
case 0: // LoRa-APRS case 0: // LoRa-APRS
fifthLine = "LoRa Rx ----> APRS-IS"; fifthLine = "LoRa Rx ----> APRS-IS";
@@ -312,6 +327,7 @@ namespace Utils {
int firstColonIndex = packet.indexOf(":"); int firstColonIndex = packet.indexOf(":");
char nextChar = packet[firstColonIndex + 1]; char nextChar = packet[firstColonIndex + 1];
String sender = packet.substring(0,packet.indexOf(">"));
for (int i = sender.length(); i < 9; i++) { for (int i = sender.length(); i < 9; i++) {
sender += " "; sender += " ";
} }
@@ -399,13 +415,14 @@ namespace Utils {
} }
} }
bool checkValidCallsign(const String& callsign) { bool callsignIsValid(const String& callsign) {
if (callsign == "WLNK-1") return true; if (callsign == "WLNK-1") return true;
String cleanCallsign; String cleanCallsign;
if (callsign.indexOf("-") > 0) { // SSID Validation int hypenCallsignIndex = callsign.indexOf("-");
cleanCallsign = callsign.substring(0, callsign.indexOf("-")); if (hypenCallsignIndex > 0) { // SSID Validation
String ssid = callsign.substring(callsign.indexOf("-") + 1); cleanCallsign = callsign.substring(0, hypenCallsignIndex);
String ssid = callsign.substring(hypenCallsignIndex + 1);
if (ssid.indexOf("-") != -1 || ssid.length() > 2) return false; if (ssid.indexOf("-") != -1 || ssid.length() > 2) return false;
if (ssid.length() == 2 && ssid[0] == '0') return false; if (ssid.length() == 2 && ssid[0] == '0') return false;
for (int i = 0; i < ssid.length(); i++) { for (int i = 0; i < ssid.length(); i++) {

View File

@@ -160,6 +160,7 @@ namespace WEB_Utils {
Config.startupDelay = getParamIntSafe("startupDelay", Config.startupDelay); Config.startupDelay = getParamIntSafe("startupDelay", Config.startupDelay);
Config.callsign = getParamStringSafe("callsign", Config.callsign); Config.callsign = getParamStringSafe("callsign", Config.callsign);
Config.tacticalCallsign = getParamStringSafe("tacticalCallsign", Config.tacticalCallsign);
Config.wifiAutoAP.password = getParamStringSafe("wifi.autoAP.password", Config.wifiAutoAP.password); Config.wifiAutoAP.password = getParamStringSafe("wifi.autoAP.password", Config.wifiAutoAP.password);
Config.wifiAutoAP.timeout = getParamIntSafe("wifi.autoAP.timeout", Config.wifiAutoAP.timeout); Config.wifiAutoAP.timeout = getParamIntSafe("wifi.autoAP.timeout", Config.wifiAutoAP.timeout);
@@ -199,7 +200,7 @@ namespace WEB_Utils {
Config.digi.mode = getParamIntSafe("digi.mode", Config.digi.mode); Config.digi.mode = getParamIntSafe("digi.mode", Config.digi.mode);
Config.digi.ecoMode = getParamIntSafe("digi.ecoMode", Config.digi.ecoMode); Config.digi.ecoMode = getParamIntSafe("digi.ecoMode", Config.digi.ecoMode);
Config.digi.backupDigiMode = request->hasParam("digi.backupDigiMode", true);
Config.loramodule.rxActive = request->hasParam("lora.rxActive", true); Config.loramodule.rxActive = request->hasParam("lora.rxActive", true);
Config.loramodule.rxFreq = getParamIntSafe("lora.rxFreq", Config.loramodule.rxFreq); Config.loramodule.rxFreq = getParamIntSafe("lora.rxFreq", Config.loramodule.rxFreq);
@@ -213,14 +214,12 @@ namespace WEB_Utils {
Config.loramodule.txSignalBandwidth = getParamIntSafe("lora.txSignalBandwidth", Config.loramodule.txSignalBandwidth); Config.loramodule.txSignalBandwidth = getParamIntSafe("lora.txSignalBandwidth", Config.loramodule.txSignalBandwidth);
Config.loramodule.power = getParamIntSafe("lora.power", Config.loramodule.power); Config.loramodule.power = getParamIntSafe("lora.power", Config.loramodule.power);
Config.display.alwaysOn = request->hasParam("display.alwaysOn", true); Config.display.alwaysOn = request->hasParam("display.alwaysOn", true);
if (!Config.display.alwaysOn) { if (!Config.display.alwaysOn) {
Config.display.timeout = getParamIntSafe("display.timeout", Config.display.timeout); Config.display.timeout = getParamIntSafe("display.timeout", Config.display.timeout);
} }
Config.display.turn180 = request->hasParam("display.turn180", true); Config.display.turn180 = request->hasParam("display.turn180", true);
Config.battery.sendInternalVoltage = request->hasParam("battery.sendInternalVoltage", true); Config.battery.sendInternalVoltage = request->hasParam("battery.sendInternalVoltage", true);
Config.battery.monitorInternalVoltage = request->hasParam("battery.monitorInternalVoltage", true); Config.battery.monitorInternalVoltage = request->hasParam("battery.monitorInternalVoltage", true);
if (Config.battery.monitorInternalVoltage) { if (Config.battery.monitorInternalVoltage) {
@@ -242,7 +241,6 @@ namespace WEB_Utils {
} }
Config.battery.sendVoltageAsTelemetry = request->hasParam("battery.sendVoltageAsTelemetry", true); Config.battery.sendVoltageAsTelemetry = request->hasParam("battery.sendVoltageAsTelemetry", true);
Config.wxsensor.active = request->hasParam("wxsensor.active", true); Config.wxsensor.active = request->hasParam("wxsensor.active", true);
if (Config.wxsensor.active) { if (Config.wxsensor.active) {
Config.wxsensor.heightCorrection = getParamIntSafe("wxsensor.heightCorrection", Config.wxsensor.heightCorrection); Config.wxsensor.heightCorrection = getParamIntSafe("wxsensor.heightCorrection", Config.wxsensor.heightCorrection);
@@ -250,7 +248,6 @@ namespace WEB_Utils {
Config.beacon.symbol = "_"; Config.beacon.symbol = "_";
} }
Config.syslog.active = request->hasParam("syslog.active", true); Config.syslog.active = request->hasParam("syslog.active", true);
if (Config.syslog.active) { if (Config.syslog.active) {
Config.syslog.server = getParamStringSafe("syslog.server", Config.syslog.server); Config.syslog.server = getParamStringSafe("syslog.server", Config.syslog.server);
@@ -258,13 +255,11 @@ namespace WEB_Utils {
Config.syslog.logBeaconOverTCPIP = request->hasParam("syslog.logBeaconOverTCPIP", true); Config.syslog.logBeaconOverTCPIP = request->hasParam("syslog.logBeaconOverTCPIP", true);
} }
Config.tnc.enableServer = request->hasParam("tnc.enableServer", true); Config.tnc.enableServer = request->hasParam("tnc.enableServer", true);
Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true); Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true);
Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true); Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true);
Config.tnc.aprsBridgeActive = request->hasParam("tnc.aprsBridgeActive", true); Config.tnc.aprsBridgeActive = request->hasParam("tnc.aprsBridgeActive", true);
Config.mqtt.active = request->hasParam("mqtt.active", true); Config.mqtt.active = request->hasParam("mqtt.active", true);
if (Config.mqtt.active) { if (Config.mqtt.active) {
Config.mqtt.server = getParamStringSafe("mqtt.server", Config.mqtt.server); Config.mqtt.server = getParamStringSafe("mqtt.server", Config.mqtt.server);
@@ -275,7 +270,6 @@ namespace WEB_Utils {
Config.mqtt.beaconOverMqtt = request->hasParam("mqtt.beaconOverMqtt", true); Config.mqtt.beaconOverMqtt = request->hasParam("mqtt.beaconOverMqtt", true);
} }
Config.rebootMode = request->hasParam("other.rebootMode", true); Config.rebootMode = request->hasParam("other.rebootMode", true);
if (Config.rebootMode) { if (Config.rebootMode) {
Config.rebootModeTime = getParamIntSafe("other.rebootModeTime", Config.rebootModeTime); Config.rebootModeTime = getParamIntSafe("other.rebootModeTime", Config.rebootModeTime);
@@ -298,8 +292,6 @@ namespace WEB_Utils {
Config.rememberStationTime = getParamIntSafe("other.rememberStationTime", Config.rememberStationTime); Config.rememberStationTime = getParamIntSafe("other.rememberStationTime", Config.rememberStationTime);
Config.backupDigiMode = request->hasParam("other.backupDigiMode", true);
bool saveSuccess = Config.writeFile(); bool saveSuccess = Config.writeFile();
if (saveSuccess) { if (saveSuccess) {

View File

@@ -29,47 +29,54 @@ extern Configuration Config;
extern uint8_t myWiFiAPIndex; extern uint8_t myWiFiAPIndex;
extern int myWiFiAPSize; extern int myWiFiAPSize;
extern WiFi_AP *currentWiFi; extern WiFi_AP *currentWiFi;
extern bool backUpDigiMode; extern bool backupDigiMode;
extern uint32_t lastServerCheck;
bool WiFiConnected = false; bool WiFiConnected = false;
uint32_t WiFiAutoAPTime = millis(); uint32_t WiFiAutoAPTime = millis();
bool WiFiAutoAPStarted = false; bool WiFiAutoAPStarted = false;
uint32_t previousWiFiMillis = 0;
uint8_t wifiCounter = 0; uint8_t wifiCounter = 0;
uint32_t lastBackupDigiTime = millis(); uint32_t lastBackupDigiTime = millis();
uint32_t lastWiFiCheck = 0;
namespace WIFI_Utils { namespace WIFI_Utils {
void checkWiFi() { void checkWiFi() {
if (Config.digi.ecoMode == 0) { if (Config.digi.ecoMode != 0) return;
if (backUpDigiMode) { uint32_t currentTime = millis();
uint32_t WiFiCheck = millis() - lastBackupDigiTime;
if (WiFi.status() != WL_CONNECTED && WiFiCheck >= 15 * 60 * 1000) {
Serial.println("*** Stopping BackUp Digi Mode ***");
backUpDigiMode = false;
wifiCounter = 0;
} else if (WiFi.status() == WL_CONNECTED) {
Serial.println("*** WiFi Reconnect Success (Stopping Backup Digi Mode) ***");
backUpDigiMode = false;
wifiCounter = 0;
}
}
if (!backUpDigiMode && (WiFi.status() != WL_CONNECTED) && ((millis() - previousWiFiMillis) >= 30 * 1000) && !WiFiAutoAPStarted) { if (backupDigiMode) {
Serial.print(millis()); if (WiFi.status() != WL_CONNECTED && ((currentTime - lastBackupDigiTime) >= 15 * 60 * 1000)) {
Serial.println("*** Stopping BackUp Digi Mode ***");
backupDigiMode = false;
wifiCounter = 0;
} else if (WiFi.status() == WL_CONNECTED) {
Serial.println("*** WiFi Reconnect Success (Stopping Backup Digi Mode) ***");
backupDigiMode = false;
wifiCounter = 0;
}
}
if (!backupDigiMode && ((currentTime - lastWiFiCheck) >= 30 * 1000) && !WiFiAutoAPStarted) {
lastWiFiCheck = currentTime;
if (WiFi.status() == WL_CONNECTED) {
if (Config.digi.backupDigiMode && (currentTime - lastServerCheck > 30 * 1000)) {
Serial.println("*** Server Connection LOST → Backup Digi Mode ***");
backupDigiMode = true;
WiFi.disconnect();
lastBackupDigiTime = currentTime;
}
} else {
Serial.println("Reconnecting to WiFi..."); Serial.println("Reconnecting to WiFi...");
WiFi.disconnect(); WiFi.disconnect();
WIFI_Utils::startWiFi(); WIFI_Utils::startWiFi();
previousWiFiMillis = millis();
if (Config.backupDigiMode) { if (Config.digi.backupDigiMode) wifiCounter++;
wifiCounter++;
}
if (wifiCounter >= 2) { if (wifiCounter >= 2) {
Serial.println("*** Starting BackUp Digi Mode ***"); Serial.println("*** Starting BackUp Digi Mode ***");
backUpDigiMode = true; backupDigiMode = true;
lastBackupDigiTime = millis(); lastBackupDigiTime = currentTime;
} }
} }
} }
@@ -98,21 +105,21 @@ namespace WIFI_Utils {
delay(500); delay(500);
unsigned long start = millis(); unsigned long start = millis();
displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0); displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0);
Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ..."); Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.print("' ");
WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str());
while (WiFi.status() != WL_CONNECTED && wifiCounter<myWiFiAPSize) { while (WiFi.status() != WL_CONNECTED && wifiCounter < myWiFiAPSize) {
delay(500); delay(500);
#ifdef INTERNAL_LED_PIN #ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,HIGH); digitalWrite(INTERNAL_LED_PIN, HIGH);
#endif #endif
Serial.print('.'); Serial.print('.');
delay(500); delay(500);
#ifdef INTERNAL_LED_PIN #ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW); digitalWrite(INTERNAL_LED_PIN, LOW);
#endif #endif
if ((millis() - start) > 10000){ if ((millis() - start) > 10000){
delay(1000); delay(1000);
if(myWiFiAPIndex >= (myWiFiAPSize - 1)) { if (myWiFiAPIndex >= (myWiFiAPSize - 1)) {
myWiFiAPIndex = 0; myWiFiAPIndex = 0;
wifiCounter++; wifiCounter++;
} else { } else {
@@ -129,7 +136,7 @@ namespace WIFI_Utils {
} }
} }
#ifdef INTERNAL_LED_PIN #ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW); digitalWrite(INTERNAL_LED_PIN, LOW);
#endif #endif
if (WiFi.status() == WL_CONNECTED) { if (WiFi.status() == WL_CONNECTED) {
Serial.print("\nConnected as "); Serial.print("\nConnected as ");
@@ -137,7 +144,7 @@ namespace WIFI_Utils {
Serial.print(" / MAC Address: "); Serial.print(" / MAC Address: ");
Serial.println(WiFi.macAddress()); Serial.println(WiFi.macAddress());
displayShow("", " Connected!!", "" , " loading ...", 1000); displayShow("", " Connected!!", "" , " loading ...", 1000);
} else if (WiFi.status() != WL_CONNECTED) { } else {
startAP = true; startAP = true;
Serial.println("\nNot connected to WiFi! Starting Auto AP"); Serial.println("\nNot connected to WiFi! Starting Auto AP");

View File

@@ -61,9 +61,9 @@ namespace WX_Utils {
void getWxModuleAddres() { void getWxModuleAddres() {
uint8_t err, addr; uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) { for(addr = 1; addr < 0x7F; addr++) {
#if defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) #ifdef SENSOR_I2C_BUS
Wire1.beginTransmission(addr); SENSOR_I2C_BUS.beginTransmission(addr);
err = Wire1.endTransmission(); err = SENSOR_I2C_BUS.endTransmission();
#else #else
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
#ifdef LIGHTGATEWAY_PLUS_1_0 #ifdef LIGHTGATEWAY_PLUS_1_0

View File

@@ -31,7 +31,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_38 #define GPIO_WAKEUP_PIN GPIO_SEL_38
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 11 #define BOARD_I2C_SDA 11
#define BOARD_I2C_SCL 12 #define BOARD_I2C_SCL 12

View File

@@ -39,8 +39,8 @@
#define INTERNAL_LED_PIN 48 #define INTERNAL_LED_PIN 48
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define SENSOR_I2C_BUS Wire
#define OLED_SDA 5 #define BOARD_I2C_SDA 5
#define OLED_SCL 6 #define BOARD_I2C_SCL 6
#endif #endif

View File

@@ -48,6 +48,8 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 25 #define INTERNAL_LED_PIN 25
#define BATTERY_PIN 37 #define BATTERY_PIN 37
#define ADC_CTRL 21
#define ADC_CTRL_PIN 21
#define ADC_CTRL_ON_STATE LOW
#endif #endif

View File

@@ -0,0 +1,55 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU
*
* This file is part of LoRa APRS iGate.
*
* LoRa APRS iGate is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef BOARD_PINOUT_H_
#define BOARD_PINOUT_H_
// LoRa Radio
#define HAS_SX1276
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_RST_PIN 14
#define RADIO_BUSY_PIN 26
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display
#define HAS_DISPLAY
#undef OLED_SDA
#undef OLED_SCL
#undef OLED_RST
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define OLED_DISPLAY_HAS_RST_PIN
// Aditional Config
#define INTERNAL_LED_PIN 25
#define BATTERY_PIN 37
#define ADC_CTRL 21
#define ADC_CTRL_ON_STATE LOW
#endif

View File

@@ -0,0 +1,11 @@
[env:heltec-lora32-v2_915]
board = ttgo-lora32-v21
build_flags =
${common.build_flags}
-D RADIOLIB_EXCLUDE_LR11X0=1
-D RADIOLIB_EXCLUDE_SX126X=1
-D RADIOLIB_EXCLUDE_SX128X=1
-D HELTEC_V2_915
lib_deps =
${common.lib_deps}
${common.display_libs}

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 39 #define BOARD_I2C_SDA 39
#define BOARD_I2C_SCL 38 #define BOARD_I2C_SCL 38
@@ -50,7 +50,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 45 #define INTERNAL_LED_PIN 45
#define BATTERY_PIN 7 #define BATTERY_PIN 7
#define ADC_CTRL 46
#define VEXT_CTRL 18 #define ADC_CTRL_PIN 46
#define ADC_CTRL_ON_STATE HIGH
#define VEXT_CTRL_PIN 18
#define VEXT_CTRL_ON_STATE HIGH
#endif #endif

View File

@@ -34,7 +34,7 @@
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -53,7 +53,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL_PIN 37
#define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE HIGH
#endif #endif

View File

@@ -34,7 +34,7 @@
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -53,7 +53,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL_PIN 37
#define ADC_CTRL_ON_STATE HIGH
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#endif #endif

View File

@@ -0,0 +1,78 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU
*
* This file is part of LoRa APRS iGate.
*
* LoRa APRS iGate is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef BOARD_PINOUT_H_
#define BOARD_PINOUT_H_
// LoRa Radio
#define HAS_SX1262
#define HAS_TCXO
#define RADIO_SCLK_PIN 9
#define RADIO_MISO_PIN 11
#define RADIO_MOSI_PIN 10
#define RADIO_CS_PIN 8
#define RADIO_RST_PIN 12
#define RADIO_DIO1_PIN 14
#define RADIO_BUSY_PIN 13
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE_WITH_OLED_PINS
#define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
// Display
#define HAS_DISPLAY
#undef OLED_SDA
#undef OLED_SCL
#undef OLED_RST
#define OLED_SDA 17
#define OLED_SCL 18
#define OLED_RST 21
#define OLED_DISPLAY_HAS_RST_PIN
// Aditional Config
#define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1
#define ADC_CTRL_PIN 37
#define ADC_CTRL_ON_STATE HIGH
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
// GPS ??
#define VGNS_CTRL 34 // cambiar nombre para prender GPS ?
// wakeup 40
// TX 39
// RX 38
// RST 42
// PPS 41
//#define GPS_L76K
// // active low, powers the oled display and the lora antenna boost
//#define LORA_PA_POWER 7 // power en
//#define LORA_PA_EN 2
//#define LORA_PA_TX_EN 46 // enable tx
#endif

View File

@@ -0,0 +1,12 @@
[env:heltec_wifi_lora_32_V4]
board = heltec_wifi_lora_32_V3
board_build.mcu = esp32s3
build_flags =
${common.build_flags}
-D RADIOLIB_EXCLUDE_LR11X0=1
-D RADIOLIB_EXCLUDE_SX127X=1
-D RADIOLIB_EXCLUDE_SX128X=1
-D HELTEC_V4
lib_deps =
${common.lib_deps}
${common.display_libs}

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 37 #define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36 #define BOARD_I2C_SCL 36
@@ -50,7 +50,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 18 #define INTERNAL_LED_PIN 18
#define BATTERY_PIN 20 #define BATTERY_PIN 20
#define ADC_CTRL 19
#define VEXT_CTRL 45 #define ADC_CTRL_PIN 19
#define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 45
#define VEXT_CTRL_ON_STATE LOW
#endif #endif

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 37 #define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36 #define BOARD_I2C_SCL 36
@@ -50,7 +50,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 18 #define INTERNAL_LED_PIN 18
#define BATTERY_PIN 20 #define BATTERY_PIN 20
#define ADC_CTRL 19
#define VEXT_CTRL 45 #define ADC_CTRL_PIN 19
#define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 45
#define VEXT_CTRL_ON_STATE LOW
#endif #endif

View File

@@ -50,8 +50,12 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL_PIN 37
#define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42

View File

@@ -33,14 +33,17 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL_PIN 37
#define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#endif #endif

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -44,7 +44,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL_PIN 37
#define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#endif #endif

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 7 #define BOARD_I2C_SDA 7
#define BOARD_I2C_SCL 6 #define BOARD_I2C_SCL 6
@@ -44,8 +44,11 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 18 #define INTERNAL_LED_PIN 18
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define ADC_CTRL 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1
#define VEXT_CTRL 3 // To turn on GPS and TFT #define ADC_CTRL_PIN 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1
#define ADC_CTRL_ON_STATE HIGH
#define VEXT_CTRL_PIN 3 // To turn on GPS and TFT
#define VEXT_CTRL_ON_STATE HIGH
// GPS // GPS
#define HAS_GPS #define HAS_GPS

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_45 #define GPIO_WAKEUP_PIN GPIO_SEL_45
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 18 #define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8 #define BOARD_I2C_SCL 8

View File

@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_45 #define GPIO_WAKEUP_PIN GPIO_SEL_45
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 18 #define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8 #define BOARD_I2C_SCL 8