Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b5d9103ea5 | |||
| 20a5029da8 | |||
| b3cc8af180 | |||
| ca16761f68 | |||
| e593b2c670 | |||
| 08a7e0aac1 | |||
| 9b258c42ab | |||
| 8712122d33 | |||
| 9e34684627 | |||
| e4aa52241d | |||
| c840ef01fa | |||
| 98f85725f8 | |||
| 10bde884b1 | |||
| 546e4f63a4 | |||
| 87f2ec2b7b | |||
| c9c7e24aae | |||
| b86133223d | |||
| 880a41bfd8 | |||
| d610b3a90f | |||
| 23a33ed27c | |||
| 72ef827900 | |||
| b756f97f55 | |||
| 2625e7b91d | |||
| 75337d6c29 | |||
| a618383617 | |||
| 8add599838 | |||
| 83ec2265c6 | |||
| bec4f4f473 | |||
| 87a67cd2c9 | |||
| 4e48b2d02d | |||
| 607277bfe9 | |||
| c2f8596667 |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This firmware is for using ESP32 based boards with LoRa Modules and GPS to live in the APRS world.
|
This firmware is for using ESP32 based boards with LoRa Modules and GPS to live in the APRS world.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
__(This iGate Firmware works with all LoRa Tracker Firmwares (specially this <a href="https://github.com/richonguzman/LoRa_APRS_Tracker" target="_blank">LoRa APRS Tracker Firmware</a>))__
|
__(This iGate Firmware works with all LoRa Tracker Firmwares (specially this <a href="https://github.com/richonguzman/LoRa_APRS_Tracker" target="_blank">LoRa APRS Tracker Firmware</a>))__
|
||||||
<br />
|
<br />
|
||||||
@@ -12,13 +12,13 @@ ____________________________________________________
|
|||||||
# <a href="https://richonguzman.github.io/lora-igate-web-flasher/installer.html" target="_blank">WEB FLASHER/INSTALLER</a>
|
# <a href="https://richonguzman.github.io/lora-igate-web-flasher/installer.html" target="_blank">WEB FLASHER/INSTALLER</a>
|
||||||
|
|
||||||
|
|
||||||
# <a href="https://github.com/richonguzman/LoRa_APRS_iGate/blob/main/manual/LoRa_APRS_iGate_CA2RXU_Firmware_Manual.pdf" target="_blank">LoRa APRS iGate CA2RXU Firmware Manual</a>
|
# <a href="https://drive.google.com/file/d/1-jafzOWis_qOaNUl4WGVcFKjh_uCJtB6/view?usp=share_link" target="_blank">LoRa APRS iGate CA2RXU Firmware Manual</a>
|
||||||
|
|
||||||
____________________________________________________
|
____________________________________________________
|
||||||
|
|
||||||
## You can support this project to continue to grow:
|
## You can support this project to continue to grow:
|
||||||
|
|
||||||
[<img src="https://github.com/richonguzman/LoRa_APRS_Tracker/blob/main/images/github-sponsors.png">](https://github.com/sponsors/richonguzman) [<img src="https://github.com/richonguzman/LoRa_APRS_Tracker/blob/main/images/paypalme.png">](http://paypal.me/richonguzman)
|
[<img src="https://github.com/richonguzman/LoRa_APRS_Tracker/raw/main/images/github-sponsors.png">](https://github.com/sponsors/richonguzman) [<img src="https://github.com/richonguzman/LoRa_APRS_Tracker/raw/main/images/paypalme.png">](http://paypal.me/richonguzman)
|
||||||
|
|
||||||
____________________________________________________
|
____________________________________________________
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ ____________________________________________________
|
|||||||
|
|
||||||
- T-Deck Plus (and also regular T-Deck with/without GPS).
|
- T-Deck Plus (and also regular T-Deck with/without GPS).
|
||||||
|
|
||||||
- HELTEC V2, V3, V3.2, T114, Wireless Stick, Wireless Stick Lite, HT-CT62, Wireless Tracker, Wireless Paper.
|
- HELTEC V2, V3, V3.2, T114, Wireless Stick, Wireless Stick Lite V3/V3.2, HT-CT62, Wireless Tracker, Wireless Paper.
|
||||||
|
|
||||||
- RAK Wireless 4631 + 19007(or 19003)
|
- RAK Wireless 4631 + 19007(or 19003)
|
||||||
|
|
||||||
@@ -51,9 +51,12 @@ ____________________________________________________
|
|||||||
<br />
|
<br />
|
||||||
|
|
||||||
# Timeline (Versions):
|
# Timeline (Versions):
|
||||||
|
- 2025-10-15 APRS Bridge for TNC added.
|
||||||
|
- 2025-10-13 Rx and Tx Frequencies are now with fully configurable.
|
||||||
|
- 2025-10-13 Startup Delay to allow the Router/Modem to start WiFiAP before connecting.
|
||||||
|
- 2025-10-12 Choose to send Beacon on Rx or Tx frequency.
|
||||||
- 2025-10-11 User defined NTP server and send beacon over MQTT added.
|
- 2025-10-11 User defined NTP server and send beacon over MQTT added.
|
||||||
- 2025-10-10 Changed Wiki into a pdf manual.
|
- 2025-10-10 Converted the Wiki into a PDF manual.
|
||||||
- 2025-09-26 Heltec Wireless Bridge support added.
|
- 2025-09-26 Heltec Wireless Bridge support added.
|
||||||
- 2025-09-09 MQTT added (pub+sub), Status defined by Op now and many fixes more.
|
- 2025-09-09 MQTT added (pub+sub), Status defined by Op now and many fixes more.
|
||||||
- 2025-06-20 Digipeaters now with updated EcoMode (Board Sleeps until packet Rx reducing current consumption to almost 10% at idle).
|
- 2025-06-20 Digipeaters now with updated EcoMode (Board Sleeps until packet Rx reducing current consumption to almost 10% at idle).
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ lib_deps =
|
|||||||
mathieucarbou/AsyncTCP @ 3.2.5
|
mathieucarbou/AsyncTCP @ 3.2.5
|
||||||
mathieucarbou/ESPAsyncWebServer @ 3.2.3
|
mathieucarbou/ESPAsyncWebServer @ 3.2.3
|
||||||
mikalhart/TinyGPSPlus @ 1.0.3
|
mikalhart/TinyGPSPlus @ 1.0.3
|
||||||
richonguzman/APRSPacketLib @1.0.0
|
richonguzman/APRSPacketLib @1.0.4
|
||||||
display_libs =
|
display_libs =
|
||||||
adafruit/Adafruit GFX Library @ 1.11.9
|
adafruit/Adafruit GFX Library @ 1.11.9
|
||||||
adafruit/Adafruit SSD1306 @ 2.5.10
|
adafruit/Adafruit SSD1306 @ 2.5.10
|
||||||
|
|||||||
@@ -17,10 +17,11 @@
|
|||||||
"path": "WIDE1-1",
|
"path": "WIDE1-1",
|
||||||
"sendViaAPRSIS": false,
|
"sendViaAPRSIS": false,
|
||||||
"sendViaRF": false,
|
"sendViaRF": false,
|
||||||
|
"beaconFreq": 1,
|
||||||
"statusActive": false,
|
"statusActive": false,
|
||||||
"statusPacket": "",
|
"statusPacket": "",
|
||||||
"gpsActive": false,
|
"gpsActive": false,
|
||||||
"gpsAmbiguity": false
|
"ambiguityLevel": 0
|
||||||
},
|
},
|
||||||
"aprs_is": {
|
"aprs_is": {
|
||||||
"active": false,
|
"active": false,
|
||||||
@@ -35,8 +36,7 @@
|
|||||||
"blacklist": "",
|
"blacklist": "",
|
||||||
"digi": {
|
"digi": {
|
||||||
"mode": 0,
|
"mode": 0,
|
||||||
"ecoMode": 0,
|
"ecoMode": 0
|
||||||
"beaconOnRxFreq": false
|
|
||||||
},
|
},
|
||||||
"lora": {
|
"lora": {
|
||||||
"rxActive": true,
|
"rxActive": true,
|
||||||
@@ -82,7 +82,8 @@
|
|||||||
"tnc": {
|
"tnc": {
|
||||||
"enableServer": false,
|
"enableServer": false,
|
||||||
"enableSerial": false,
|
"enableSerial": false,
|
||||||
"acceptOwn": false
|
"acceptOwn": false,
|
||||||
|
"aprsBrigdeActive": false
|
||||||
},
|
},
|
||||||
"mqtt": {
|
"mqtt": {
|
||||||
"active": false,
|
"active": false,
|
||||||
|
|||||||
@@ -144,8 +144,7 @@
|
|||||||
name="beacon.comment"
|
name="beacon.comment"
|
||||||
id="beacon.comment"
|
id="beacon.comment"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder="LoRa APRS"
|
placeholder=""
|
||||||
required=""
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
@@ -189,18 +188,10 @@
|
|||||||
name="action.symbol"
|
name="action.symbol"
|
||||||
id="action.symbol"
|
id="action.symbol"
|
||||||
>
|
>
|
||||||
<option value="L#">
|
<option value="L#">Green star with L</option>
|
||||||
Green star with L
|
<option value="L_">Blue circle with L</option>
|
||||||
</option>
|
<option value="L&">Black diamond with L</option>
|
||||||
<option value="L_">
|
<option value="La" selected>Red diamond with L</option>
|
||||||
Blue circle with L
|
|
||||||
</option>
|
|
||||||
<option value="L&">
|
|
||||||
Black diamond with L
|
|
||||||
</option>
|
|
||||||
<option value="La">
|
|
||||||
Red diamond with L
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -567,11 +558,28 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 d-grid gap-2">
|
</div>
|
||||||
<button class="btn btn-primary" id="send-beacon">Send beacon now</button>
|
<div class="row mt-3">
|
||||||
|
<div class="col-6">
|
||||||
|
<button class="btn btn-primary form-control h-100" id="send-beacon">Send beacon now</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<label
|
||||||
|
for="beacon.beaconFreq"
|
||||||
|
class="form-label">
|
||||||
|
<small>(Select LoRa Beacon Frequency)</small>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
class="form-select form-select"
|
||||||
|
name="beacon.beaconFreq"
|
||||||
|
id="beacon.beaconFreq"
|
||||||
|
>
|
||||||
|
<option value="0">Beacon on Rx Freq</option>
|
||||||
|
<option value="1">Beacon on Tx Freq</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-4">
|
<div class="row mt-3">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label
|
<label
|
||||||
for="beacon.interval"
|
for="beacon.interval"
|
||||||
@@ -594,6 +602,23 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<label
|
||||||
|
for="beacon.ambiguityLevel"
|
||||||
|
class="form-label"
|
||||||
|
>APRS Position Ambiguity</label
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
class="form-select form-select"
|
||||||
|
name="beacon.ambiguityLevel"
|
||||||
|
id="beacon.ambiguityLevel"
|
||||||
|
>
|
||||||
|
<option value="0" selected>No Ambiguity</option>
|
||||||
|
<option value="1">~110 m forced Ambiguity</option>
|
||||||
|
<option value="2">~1.1 km forced Ambiguity</option>
|
||||||
|
<option value="3">~11 km forced Ambiguity</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
@@ -610,21 +635,6 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
|
||||||
<div class="form-check form-switch">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="beacon.gpsAmbiguity"
|
|
||||||
id="beacon.gpsAmbiguity"
|
|
||||||
class="form-check-input"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="beacon.gpsAmbiguity"
|
|
||||||
class="form-label"
|
|
||||||
>Send Real-GPS Beacon with Ambiguity <small>(~ 1 Km of Random Error)</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
@@ -646,7 +656,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Black List
|
Black List
|
||||||
</h5>
|
</h5>
|
||||||
<small>Add Callsigns with space between them to Blacklist them (* wild card allowed)</small>
|
<small>Add Callsigns with space between them to Blacklist (* wildcard allowed)</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -702,15 +712,9 @@
|
|||||||
name="digi.mode"
|
name="digi.mode"
|
||||||
id="digi.mode"
|
id="digi.mode"
|
||||||
>
|
>
|
||||||
<option value="0">
|
<option value="0" selected>OFF</option>
|
||||||
OFF
|
<option value="2">WIDE1 (fill-in) Digi</option>
|
||||||
</option>
|
<option value="3">WIDE2 (+WIDE1) Digi</option>
|
||||||
<option value="2">
|
|
||||||
WIDE1 (fill-in) Digi
|
|
||||||
</option>
|
|
||||||
<option value="3">
|
|
||||||
WIDE2 (+WIDE1) Digi
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 mt-3">
|
<div class="col-12 mt-3">
|
||||||
@@ -727,37 +731,9 @@
|
|||||||
name="digi.ecoMode"
|
name="digi.ecoMode"
|
||||||
id="digi.ecoMode"
|
id="digi.ecoMode"
|
||||||
>
|
>
|
||||||
<option value="0">
|
<option value="0" selected>OFF (Normal Mode - WiFiAP and Serial Output enabled)</option>
|
||||||
OFF (Normal Mode - WiFiAP and Serial Output enabled)
|
<option value="1">Ultra Eco Mode (Sleep till Packet Rx (WiFiAP/WebUI & Display disabled))</option>
|
||||||
</option>
|
<option value="2">OFF (Normal Mode - WiFiAP disabled but Serial Output still enabled)</option>
|
||||||
<option value="1">
|
|
||||||
Ultra Eco Mode (Sleep till Packet Rx (WiFiAP/WebUI & Display disabled))
|
|
||||||
</option>
|
|
||||||
<option value="2">
|
|
||||||
OFF (Normal Mode - WiFiAP disabled but Serial Output still enabled)
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 mt-3">
|
|
||||||
<label
|
|
||||||
for="digi.beaconOnRxFreq"
|
|
||||||
class="form-label"
|
|
||||||
>Digipeater Beacon Frequency
|
|
||||||
<small
|
|
||||||
>(If Rx Freq different from Tx Freq).</small
|
|
||||||
></label
|
|
||||||
>
|
|
||||||
<select
|
|
||||||
class="form-select form-select"
|
|
||||||
name="digi.beaconOnRxFreq"
|
|
||||||
id="digi.beaconOnRxFreq"
|
|
||||||
>
|
|
||||||
<option value="false">
|
|
||||||
Beacon on Tx Freq
|
|
||||||
</option>
|
|
||||||
<option value="true">
|
|
||||||
Beacon on Rx Freq
|
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1512,25 +1488,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">
|
||||||
<div class="form-check form-switch">
|
|
||||||
<div class="form-text">
|
|
||||||
Server will be available at port <strong>8001</strong>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="tnc.enableServer"
|
|
||||||
id="tnc.enableServer"
|
|
||||||
class="form-check-input"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="tnc.enableServer"
|
|
||||||
class="form-label"
|
|
||||||
>Enable TNC server</label
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -1545,7 +1503,24 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-6">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="tnc.enableServer"
|
||||||
|
id="tnc.enableServer"
|
||||||
|
class="form-check-input"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
for="tnc.enableServer"
|
||||||
|
class="form-label"
|
||||||
|
>Enable TNC server <small><strong>(Port 8001)</strong></small></label
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-2">
|
||||||
|
<div class="col-6">
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -1560,6 +1535,21 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="tnc.aprsBridgeActive"
|
||||||
|
id="tnc.aprsBridgeActive"
|
||||||
|
class="form-check-input"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
for="tnc.aprsBridgeActive"
|
||||||
|
class="form-label"
|
||||||
|
>Enable APRS Bridge</label
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -119,7 +119,11 @@ function loadSettings(settings) {
|
|||||||
document.getElementById("beacon.interval").value = settings.beacon.interval;
|
document.getElementById("beacon.interval").value = settings.beacon.interval;
|
||||||
document.getElementById("other.rememberStationTime").value = settings.other.rememberStationTime;
|
document.getElementById("other.rememberStationTime").value = settings.other.rememberStationTime;
|
||||||
document.getElementById("beacon.sendViaAPRSIS").checked = settings.beacon.sendViaAPRSIS;
|
document.getElementById("beacon.sendViaAPRSIS").checked = settings.beacon.sendViaAPRSIS;
|
||||||
|
|
||||||
document.getElementById("beacon.sendViaRF").checked = settings.beacon.sendViaRF;
|
document.getElementById("beacon.sendViaRF").checked = settings.beacon.sendViaRF;
|
||||||
|
document.getElementById("beacon.beaconFreq").value = settings.beacon.beaconFreq;
|
||||||
|
BeaconingViaRFCheckbox.checked = settings.beacon.sendViaRF;
|
||||||
|
BeaconingFrequency.disabled = !BeaconingViaRFCheckbox.checked;
|
||||||
|
|
||||||
document.getElementById("beacon.statusActive").checked = settings.beacon.statusActive;
|
document.getElementById("beacon.statusActive").checked = settings.beacon.statusActive;
|
||||||
document.getElementById("beacon.statusPacket").value = settings.beacon.statusPacket;
|
document.getElementById("beacon.statusPacket").value = settings.beacon.statusPacket;
|
||||||
@@ -127,7 +131,7 @@ function loadSettings(settings) {
|
|||||||
StatusPacket.disabled = !StatusCheckbox.checked;
|
StatusPacket.disabled = !StatusCheckbox.checked;
|
||||||
|
|
||||||
document.getElementById("beacon.gpsActive").checked = settings.beacon.gpsActive;
|
document.getElementById("beacon.gpsActive").checked = settings.beacon.gpsActive;
|
||||||
document.getElementById("beacon.gpsAmbiguity").checked = settings.beacon.gpsAmbiguity;
|
document.getElementById("beacon.ambiguityLevel").value = settings.beacon.ambiguityLevel;
|
||||||
|
|
||||||
// Black List
|
// Black List
|
||||||
document.getElementById("blacklist").value = settings.blacklist;
|
document.getElementById("blacklist").value = settings.blacklist;
|
||||||
@@ -135,7 +139,6 @@ 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.beaconOnRxFreq").value = settings.digi.beaconOnRxFreq;
|
|
||||||
|
|
||||||
// LoRa
|
// LoRa
|
||||||
document.getElementById("lora.rxActive").checked = settings.lora.rxActive;
|
document.getElementById("lora.rxActive").checked = settings.lora.rxActive;
|
||||||
@@ -203,6 +206,7 @@ function loadSettings(settings) {
|
|||||||
document.getElementById("tnc.enableServer").checked = settings.tnc.enableServer;
|
document.getElementById("tnc.enableServer").checked = settings.tnc.enableServer;
|
||||||
document.getElementById("tnc.enableSerial").checked = settings.tnc.enableSerial;
|
document.getElementById("tnc.enableSerial").checked = settings.tnc.enableSerial;
|
||||||
document.getElementById("tnc.acceptOwn").checked = settings.tnc.acceptOwn;
|
document.getElementById("tnc.acceptOwn").checked = settings.tnc.acceptOwn;
|
||||||
|
document.getElementById("tnc.aprsBridgeActive").checked = settings.tnc.aprsBridgeActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MQTT
|
// MQTT
|
||||||
@@ -212,7 +216,7 @@ function loadSettings(settings) {
|
|||||||
document.getElementById("mqtt.username").value = settings.mqtt.username;
|
document.getElementById("mqtt.username").value = settings.mqtt.username;
|
||||||
document.getElementById("mqtt.password").value = settings.mqtt.password;
|
document.getElementById("mqtt.password").value = settings.mqtt.password;
|
||||||
document.getElementById("mqtt.port").value = settings.mqtt.port;
|
document.getElementById("mqtt.port").value = settings.mqtt.port;
|
||||||
document.getElementById("mqtt.beaconOverMqtt").value = settings.mqtt.beaconOverMqtt;
|
document.getElementById("mqtt.beaconOverMqtt").checked = settings.mqtt.beaconOverMqtt;
|
||||||
MqttCheckbox.checked = settings.mqtt.active;
|
MqttCheckbox.checked = settings.mqtt.active;
|
||||||
MqttServer.disabled = !MqttCheckbox.check;
|
MqttServer.disabled = !MqttCheckbox.check;
|
||||||
MqttTopic.disabled = !MqttCheckbox.check;
|
MqttTopic.disabled = !MqttCheckbox.check;
|
||||||
@@ -306,6 +310,12 @@ function updateImage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Beaconing Switches
|
||||||
|
const BeaconingViaRFCheckbox = document.querySelector('input[name="beacon.sendViaRF"]');
|
||||||
|
const BeaconingFrequency = document.querySelector('select[name="beacon.beaconFreq"]');
|
||||||
|
BeaconingViaRFCheckbox.addEventListener("change", function() {
|
||||||
|
BeaconingFrequency.disabled = !this.checked;
|
||||||
|
});
|
||||||
|
|
||||||
// Status Switch
|
// Status Switch
|
||||||
const StatusCheckbox = document.querySelector('input[name="beacon.statusActive"]');
|
const StatusCheckbox = document.querySelector('input[name="beacon.statusActive"]');
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 141 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 711 KiB |
@@ -45,12 +45,13 @@ public:
|
|||||||
String overlay;
|
String overlay;
|
||||||
String symbol;
|
String symbol;
|
||||||
String path;
|
String path;
|
||||||
bool sendViaRF;
|
|
||||||
bool sendViaAPRSIS;
|
bool sendViaAPRSIS;
|
||||||
bool gpsActive;
|
bool sendViaRF;
|
||||||
bool gpsAmbiguity;
|
int beaconFreq;
|
||||||
bool statusActive;
|
bool statusActive;
|
||||||
String statusPacket;
|
String statusPacket;
|
||||||
|
bool gpsActive;
|
||||||
|
int ambiguityLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class APRS_IS {
|
class APRS_IS {
|
||||||
@@ -67,8 +68,7 @@ public:
|
|||||||
class DIGI {
|
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 beaconOnRxFreq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoraModule {
|
class LoraModule {
|
||||||
@@ -127,6 +127,7 @@ public:
|
|||||||
bool enableServer;
|
bool enableServer;
|
||||||
bool enableSerial;
|
bool enableSerial;
|
||||||
bool acceptOwn;
|
bool acceptOwn;
|
||||||
|
bool aprsBridgeActive;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OTA {
|
class OTA {
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ namespace TNC_Utils {
|
|||||||
void setup();
|
void setup();
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
void sendToClients(const String& packet);
|
void sendToClients(const String& packet, bool stripBytes = false);
|
||||||
void sendToSerial(const String& packet);
|
void sendToSerial(const String& packet, bool stripBytes = false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ ___________________________________________________________________*/
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
String versionDate = "2025-10-13";
|
String versionDate = "2025-11-30";
|
||||||
String versionNumber = "3.1.3";
|
String versionNumber = "3.1.5";
|
||||||
Configuration Config;
|
Configuration Config;
|
||||||
WiFiClient aprsIsClient;
|
WiFiClient aprsIsClient;
|
||||||
WiFiClient mqttClient;
|
WiFiClient mqttClient;
|
||||||
@@ -192,9 +192,9 @@ void loop() {
|
|||||||
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
|
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.tnc.enableServer) TNC_Utils::sendToClients(packet); // Send received packet to TNC KISS
|
if (Config.tnc.enableServer) TNC_Utils::sendToClients(packet, true); // Send received packet to TNC KISS
|
||||||
if (Config.tnc.enableSerial) TNC_Utils::sendToSerial(packet); // Send received packet to Serial KISS
|
if (Config.tnc.enableSerial) TNC_Utils::sendToSerial(packet, true); // Send received packet to Serial KISS
|
||||||
if (Config.mqtt.active) MQTT_Utils::sendToMqtt(packet); // Send received packet to MQTT
|
if (Config.mqtt.active) MQTT_Utils::sendToMqtt(packet); // Send received packet to MQTT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.aprs_is.active) APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS
|
if (Config.aprs_is.active) APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
|
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <APRSPacketLib.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "aprs_is_utils.h"
|
#include "aprs_is_utils.h"
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
#include "query_utils.h"
|
#include "query_utils.h"
|
||||||
#include "A7670_utils.h"
|
#include "A7670_utils.h"
|
||||||
#include "digi_utils.h"
|
#include "digi_utils.h"
|
||||||
|
#include "tnc_utils.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
@@ -235,12 +237,7 @@ namespace APRS_IS_Utils {
|
|||||||
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType) {
|
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType) {
|
||||||
String packet = aprsisPacket;
|
String packet = aprsisPacket;
|
||||||
packet.trim();
|
packet.trim();
|
||||||
String outputPacket = Config.callsign;
|
String outputPacket = APRSPacketLib::generateBasePacket(Config.callsign, "APLRG1", Config.beacon.path);
|
||||||
outputPacket += ">APLRG1";
|
|
||||||
if (Config.beacon.path != "") {
|
|
||||||
outputPacket += ",";
|
|
||||||
outputPacket += Config.beacon.path;
|
|
||||||
}
|
|
||||||
outputPacket += ":}";
|
outputPacket += ":}";
|
||||||
outputPacket += packet.substring(0, packet.indexOf(",")); // Callsign>Tocall
|
outputPacket += packet.substring(0, packet.indexOf(",")); // Callsign>Tocall
|
||||||
outputPacket.concat(",TCPIP,");
|
outputPacket.concat(",TCPIP,");
|
||||||
@@ -367,6 +364,10 @@ namespace APRS_IS_Utils {
|
|||||||
Serial.println(" ---> Rejected (Time): No Tx");
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,15 +68,17 @@ bool Configuration::writeFile() {
|
|||||||
data["beacon"]["longitude"] = beacon.longitude;
|
data["beacon"]["longitude"] = beacon.longitude;
|
||||||
data["beacon"]["overlay"] = beacon.overlay;
|
data["beacon"]["overlay"] = beacon.overlay;
|
||||||
data["beacon"]["symbol"] = beacon.symbol;
|
data["beacon"]["symbol"] = beacon.symbol;
|
||||||
|
data["beacon"]["path"] = beacon.path;
|
||||||
|
|
||||||
data["beacon"]["sendViaAPRSIS"] = beacon.sendViaAPRSIS;
|
data["beacon"]["sendViaAPRSIS"] = beacon.sendViaAPRSIS;
|
||||||
data["beacon"]["sendViaRF"] = beacon.sendViaRF;
|
data["beacon"]["sendViaRF"] = beacon.sendViaRF;
|
||||||
data["beacon"]["path"] = beacon.path;
|
data["beacon"]["beaconFreq"] = beacon.beaconFreq;
|
||||||
|
|
||||||
data["beacon"]["statusActive"] = beacon.statusActive;
|
data["beacon"]["statusActive"] = beacon.statusActive;
|
||||||
data["beacon"]["statusPacket"] = beacon.statusPacket;
|
data["beacon"]["statusPacket"] = beacon.statusPacket;
|
||||||
|
|
||||||
data["beacon"]["gpsActive"] = beacon.gpsActive;
|
data["beacon"]["gpsActive"] = beacon.gpsActive;
|
||||||
data["beacon"]["gpsAmbiguity"] = beacon.gpsAmbiguity;
|
data["beacon"]["ambiguityLevel"] = beacon.ambiguityLevel;
|
||||||
|
|
||||||
data["personalNote"] = personalNote;
|
data["personalNote"] = personalNote;
|
||||||
|
|
||||||
@@ -87,7 +89,6 @@ 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"]["beaconOnRxFreq"] = digi.beaconOnRxFreq;
|
|
||||||
|
|
||||||
data["lora"]["rxActive"] = loramodule.rxActive;
|
data["lora"]["rxActive"] = loramodule.rxActive;
|
||||||
data["lora"]["rxFreq"] = loramodule.rxFreq;
|
data["lora"]["rxFreq"] = loramodule.rxFreq;
|
||||||
@@ -130,6 +131,7 @@ bool Configuration::writeFile() {
|
|||||||
data["tnc"]["enableServer"] = tnc.enableServer;
|
data["tnc"]["enableServer"] = tnc.enableServer;
|
||||||
data["tnc"]["enableSerial"] = tnc.enableSerial;
|
data["tnc"]["enableSerial"] = tnc.enableSerial;
|
||||||
data["tnc"]["acceptOwn"] = tnc.acceptOwn;
|
data["tnc"]["acceptOwn"] = tnc.acceptOwn;
|
||||||
|
data["tnc"]["aprsBridgeActive"] = tnc.aprsBridgeActive;
|
||||||
|
|
||||||
data["mqtt"]["active"] = mqtt.active;
|
data["mqtt"]["active"] = mqtt.active;
|
||||||
data["mqtt"]["server"] = mqtt.server;
|
data["mqtt"]["server"] = mqtt.server;
|
||||||
@@ -226,10 +228,11 @@ bool Configuration::readFile() {
|
|||||||
!data["beacon"].containsKey("path") ||
|
!data["beacon"].containsKey("path") ||
|
||||||
!data["beacon"].containsKey("sendViaAPRSIS") ||
|
!data["beacon"].containsKey("sendViaAPRSIS") ||
|
||||||
!data["beacon"].containsKey("sendViaRF") ||
|
!data["beacon"].containsKey("sendViaRF") ||
|
||||||
|
!data["beacon"].containsKey("beaconFreq") ||
|
||||||
!data["beacon"].containsKey("statusActive") ||
|
!data["beacon"].containsKey("statusActive") ||
|
||||||
!data["beacon"].containsKey("statusPacket") ||
|
!data["beacon"].containsKey("statusPacket") ||
|
||||||
!data["beacon"].containsKey("gpsActive") ||
|
!data["beacon"].containsKey("gpsActive") ||
|
||||||
!data["beacon"].containsKey("gpsAmbiguity")) needsRewrite = true;
|
!data["beacon"].containsKey("ambiguityLevel")) needsRewrite = true;
|
||||||
beacon.latitude = data["beacon"]["latitude"] | 0.0;
|
beacon.latitude = data["beacon"]["latitude"] | 0.0;
|
||||||
beacon.longitude = data["beacon"]["longitude"] | 0.0;
|
beacon.longitude = data["beacon"]["longitude"] | 0.0;
|
||||||
beacon.comment = data["beacon"]["comment"] | "LoRa APRS";
|
beacon.comment = data["beacon"]["comment"] | "LoRa APRS";
|
||||||
@@ -239,10 +242,11 @@ bool Configuration::readFile() {
|
|||||||
beacon.path = data["beacon"]["path"] | "WIDE1-1";
|
beacon.path = data["beacon"]["path"] | "WIDE1-1";
|
||||||
beacon.sendViaAPRSIS = data["beacon"]["sendViaAPRSIS"] | false;
|
beacon.sendViaAPRSIS = data["beacon"]["sendViaAPRSIS"] | false;
|
||||||
beacon.sendViaRF = data["beacon"]["sendViaRF"] | false;
|
beacon.sendViaRF = data["beacon"]["sendViaRF"] | false;
|
||||||
|
beacon.beaconFreq = data["beacon"]["beaconFreq"] | 1;
|
||||||
beacon.statusActive = data["beacon"]["statusActive"] | false;
|
beacon.statusActive = data["beacon"]["statusActive"] | false;
|
||||||
beacon.statusPacket = data["beacon"]["statusPacket"] | "";
|
beacon.statusPacket = data["beacon"]["statusPacket"] | "";
|
||||||
beacon.gpsActive = data["beacon"]["gpsActive"] | false;
|
beacon.gpsActive = data["beacon"]["gpsActive"] | false;
|
||||||
beacon.gpsAmbiguity = data["beacon"]["gpsAmbiguity"] | false;
|
beacon.ambiguityLevel = data["beacon"]["ambiguityLevel"] | 0;
|
||||||
|
|
||||||
if (!data.containsKey("personalNote")) needsRewrite = true;
|
if (!data.containsKey("personalNote")) needsRewrite = true;
|
||||||
personalNote = data["personalNote"] | "personal note here";
|
personalNote = data["personalNote"] | "personal note here";
|
||||||
@@ -251,13 +255,10 @@ 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") ||
|
!data["digi"].containsKey("ecoMode")) needsRewrite = true;
|
||||||
!data["digi"].containsKey("beaconOnRxFreq")) 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;
|
||||||
digi.beaconOnRxFreq = data["digi"]["beaconOnRxFreq"] | 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
|
||||||
@@ -331,10 +332,12 @@ bool Configuration::readFile() {
|
|||||||
|
|
||||||
if (!data["tnc"].containsKey("enableServer") ||
|
if (!data["tnc"].containsKey("enableServer") ||
|
||||||
!data["tnc"].containsKey("enableSerial") ||
|
!data["tnc"].containsKey("enableSerial") ||
|
||||||
!data["tnc"].containsKey("acceptOwn")) needsRewrite = true;
|
!data["tnc"].containsKey("acceptOwn") ||
|
||||||
|
!data["tnc"].containsKey("aprsBridgeActive")) needsRewrite = true;
|
||||||
tnc.enableServer = data["tnc"]["enableServer"] | false;
|
tnc.enableServer = data["tnc"]["enableServer"] | false;
|
||||||
tnc.enableSerial = data["tnc"]["enableSerial"] | false;
|
tnc.enableSerial = data["tnc"]["enableSerial"] | false;
|
||||||
tnc.acceptOwn = data["tnc"]["acceptOwn"] | false;
|
tnc.acceptOwn = data["tnc"]["acceptOwn"] | false;
|
||||||
|
tnc.aprsBridgeActive = data["tnc"]["aprsBridgeActive"] | false;
|
||||||
|
|
||||||
if (!data["mqtt"].containsKey("active") ||
|
if (!data["mqtt"].containsKey("active") ||
|
||||||
!data["mqtt"].containsKey("server") ||
|
!data["mqtt"].containsKey("server") ||
|
||||||
@@ -436,15 +439,17 @@ void Configuration::setDefaultValues() {
|
|||||||
beacon.interval = 15;
|
beacon.interval = 15;
|
||||||
beacon.overlay = "L";
|
beacon.overlay = "L";
|
||||||
beacon.symbol = "a";
|
beacon.symbol = "a";
|
||||||
beacon.sendViaAPRSIS = true;
|
|
||||||
beacon.sendViaRF = false;
|
|
||||||
beacon.path = "WIDE1-1";
|
beacon.path = "WIDE1-1";
|
||||||
|
|
||||||
|
beacon.sendViaAPRSIS = true;
|
||||||
|
beacon.sendViaRF = false;
|
||||||
|
beacon.beaconFreq = 1;
|
||||||
|
|
||||||
beacon.statusActive = false;
|
beacon.statusActive = false;
|
||||||
beacon.statusPacket = "";
|
beacon.statusPacket = "";
|
||||||
|
|
||||||
beacon.gpsActive = false;
|
beacon.gpsActive = false;
|
||||||
beacon.gpsAmbiguity = false;
|
beacon.ambiguityLevel = 0;
|
||||||
|
|
||||||
personalNote = "";
|
personalNote = "";
|
||||||
|
|
||||||
@@ -452,7 +457,6 @@ void Configuration::setDefaultValues() {
|
|||||||
|
|
||||||
digi.mode = 0;
|
digi.mode = 0;
|
||||||
digi.ecoMode = 0;
|
digi.ecoMode = 0;
|
||||||
digi.beaconOnRxFreq = false;
|
|
||||||
|
|
||||||
loramodule.rxActive = true;
|
loramodule.rxActive = true;
|
||||||
loramodule.rxFreq = 433775000;
|
loramodule.rxFreq = 433775000;
|
||||||
@@ -495,6 +499,7 @@ void Configuration::setDefaultValues() {
|
|||||||
tnc.enableServer = false;
|
tnc.enableServer = false;
|
||||||
tnc.enableSerial = false;
|
tnc.enableSerial = false;
|
||||||
tnc.acceptOwn = false;
|
tnc.acceptOwn = false;
|
||||||
|
tnc.aprsBridgeActive = false;
|
||||||
|
|
||||||
mqtt.active = false;
|
mqtt.active = false;
|
||||||
mqtt.server = "";
|
mqtt.server = "";
|
||||||
@@ -524,7 +529,7 @@ void Configuration::setDefaultValues() {
|
|||||||
|
|
||||||
backupDigiMode = false;
|
backupDigiMode = false;
|
||||||
|
|
||||||
Serial.println("All is Written!");
|
Serial.println("New Data Created... All is Written!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration::Configuration() {
|
Configuration::Configuration() {
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ void displaySetup() {
|
|||||||
#ifdef HAS_EPAPER
|
#ifdef HAS_EPAPER
|
||||||
display.landscape();
|
display.landscape();
|
||||||
display.printCenter("LoRa APRS iGate Initialising...");
|
display.printCenter("LoRa APRS iGate Initialising...");
|
||||||
|
if (Config.display.turn180) display.setRotation(2);
|
||||||
display.update();
|
display.update();
|
||||||
#else
|
#else
|
||||||
#ifdef OLED_DISPLAY_HAS_RST_PIN
|
#ifdef OLED_DISPLAY_HAS_RST_PIN
|
||||||
@@ -106,7 +107,7 @@ void displaySetup() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(TTGO_T_Beam_S3_SUPREME_V3)
|
#if defined(TTGO_T_Beam_S3_SUPREME_V3)
|
||||||
if (!display.begin(0x3c, false)) {
|
if (display.begin(0x3c, false)) {
|
||||||
displayFound = true;
|
displayFound = true;
|
||||||
if (Config.display.turn180) display.setRotation(2);
|
if (Config.display.turn180) display.setRotation(2);
|
||||||
display.clearDisplay();
|
display.clearDisplay();
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
|
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <APRSPacketLib.h>
|
||||||
#include <TinyGPS++.h>
|
#include <TinyGPS++.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
@@ -42,70 +43,6 @@ namespace GPS_Utils {
|
|||||||
return iGateLoRaBeaconPacket;
|
return iGateLoRaBeaconPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ax25_base91enc(char *s, uint8_t n, uint32_t v) {
|
|
||||||
for(s += n, *s = '\0'; n; n--) {
|
|
||||||
*(--s) = v % 91 + 33;
|
|
||||||
v /= 91;
|
|
||||||
}
|
|
||||||
return(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
float roundToTwoDecimals(float degrees) {
|
|
||||||
return round(degrees * 100) / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
String encodeGPS(float latitude, float longitude, const String& overlay, const String& symbol) {
|
|
||||||
String encodedData = overlay;
|
|
||||||
uint32_t aprs_lat, aprs_lon;
|
|
||||||
|
|
||||||
float processedLatitude = latitude;
|
|
||||||
float processedLongitude = longitude;
|
|
||||||
if (Config.beacon.gpsActive && Config.beacon.gpsAmbiguity) {
|
|
||||||
processedLatitude = roundToTwoDecimals(latitude);
|
|
||||||
processedLongitude = roundToTwoDecimals(longitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
aprs_lat = 900000000 - processedLatitude * 10000000;
|
|
||||||
aprs_lat = aprs_lat / 26 - aprs_lat / 2710 + aprs_lat / 15384615;
|
|
||||||
aprs_lon = 900000000 + processedLongitude * 10000000 / 2;
|
|
||||||
aprs_lon = aprs_lon / 26 - aprs_lon / 2710 + aprs_lon / 15384615;
|
|
||||||
|
|
||||||
String Ns, Ew, helper;
|
|
||||||
if(processedLatitude < 0) { Ns = "S"; } else { Ns = "N"; }
|
|
||||||
if(processedLatitude < 0) { processedLatitude = -processedLatitude; }
|
|
||||||
|
|
||||||
if(processedLongitude < 0) { Ew = "W"; } else { Ew = "E"; }
|
|
||||||
if(processedLongitude < 0) { processedLongitude = -processedLongitude; }
|
|
||||||
|
|
||||||
char helper_base91[] = {"0000\0"};
|
|
||||||
int i;
|
|
||||||
ax25_base91enc(helper_base91, 4, aprs_lat);
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
encodedData += helper_base91[i];
|
|
||||||
}
|
|
||||||
ax25_base91enc(helper_base91, 4, aprs_lon);
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
encodedData += helper_base91[i];
|
|
||||||
}
|
|
||||||
encodedData += symbol;
|
|
||||||
encodedData += " ";
|
|
||||||
encodedData += "\x47";
|
|
||||||
return encodedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void generateBeaconFirstPart() {
|
|
||||||
String beaconPacket = Config.callsign;
|
|
||||||
beaconPacket += ">APLRG1";
|
|
||||||
if (Config.beacon.path.indexOf("WIDE") == 0) {
|
|
||||||
beaconPacket += ",";
|
|
||||||
beaconPacket += Config.beacon.path;
|
|
||||||
}
|
|
||||||
iGateBeaconPacket = beaconPacket;
|
|
||||||
iGateBeaconPacket += ",qAC:!";
|
|
||||||
iGateLoRaBeaconPacket = beaconPacket;
|
|
||||||
iGateLoRaBeaconPacket += ":!";
|
|
||||||
}
|
|
||||||
|
|
||||||
void generateBeacons() {
|
void generateBeacons() {
|
||||||
if (Config.callsign.indexOf("NOCALL-10") != 0 && !Utils::checkValidCallsign(Config.callsign)) {
|
if (Config.callsign.indexOf("NOCALL-10") != 0 && !Utils::checkValidCallsign(Config.callsign)) {
|
||||||
displayShow("***** ERROR ******", "CALLSIGN = NOT VALID!", "", "Only Rx Mode Active", 3000);
|
displayShow("***** ERROR ******", "CALLSIGN = NOT VALID!", "", "Only Rx Mode Active", 3000);
|
||||||
@@ -116,9 +53,17 @@ namespace GPS_Utils {
|
|||||||
Config.digi.mode = 0;
|
Config.digi.mode = 0;
|
||||||
Config.backupDigiMode = false;
|
Config.backupDigiMode = false;
|
||||||
}
|
}
|
||||||
generateBeaconFirstPart();
|
String beaconPacket = APRSPacketLib::generateBasePacket(Config.callsign, "APLRG1", Config.beacon.path);
|
||||||
String encodedGPS = encodeGPS(Config.beacon.latitude, Config.beacon.longitude, Config.beacon.overlay, Config.beacon.symbol);
|
String encodedGPS = APRSPacketLib::encodeGPSIntoBase91(Config.beacon.latitude, Config.beacon.longitude, 0, 0, Config.beacon.symbol, false, 0, true, Config.beacon.ambiguityLevel);
|
||||||
|
|
||||||
|
iGateBeaconPacket = beaconPacket;
|
||||||
|
iGateBeaconPacket += ",qAC:!";
|
||||||
|
iGateBeaconPacket += Config.beacon.overlay;
|
||||||
iGateBeaconPacket += encodedGPS;
|
iGateBeaconPacket += encodedGPS;
|
||||||
|
|
||||||
|
iGateLoRaBeaconPacket = beaconPacket;
|
||||||
|
iGateLoRaBeaconPacket += ":=";
|
||||||
|
iGateLoRaBeaconPacket += Config.beacon.overlay;
|
||||||
iGateLoRaBeaconPacket += encodedGPS;
|
iGateLoRaBeaconPacket += encodedGPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,47 +71,40 @@ namespace GPS_Utils {
|
|||||||
return TinyGPSPlus::distanceBetween(Config.beacon.latitude,Config.beacon.longitude, latitude, longitude) / 1000.0;
|
return TinyGPSPlus::distanceBetween(Config.beacon.latitude,Config.beacon.longitude, latitude, longitude) / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String buildDistanceAndComment(float latitude, float longitude, const String& comment) {
|
||||||
|
distance = String(calculateDistanceTo(latitude, longitude),1);
|
||||||
|
|
||||||
|
String distanceAndComment = String(latitude,5);
|
||||||
|
distanceAndComment += "N / ";
|
||||||
|
distanceAndComment += String(longitude,5);
|
||||||
|
distanceAndComment += "E / ";
|
||||||
|
distanceAndComment += distance;
|
||||||
|
distanceAndComment += "km";
|
||||||
|
|
||||||
|
if (comment != "") {
|
||||||
|
distanceAndComment += " / ";
|
||||||
|
distanceAndComment += comment;
|
||||||
|
}
|
||||||
|
return distanceAndComment;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
String decodeEncodedGPS(const String& packet) {
|
String decodeEncodedGPS(const String& packet) {
|
||||||
int indexOfExclamation = packet.indexOf(":!");
|
int indexOfExclamation = packet.indexOf(":!");
|
||||||
int indexOfEqual = packet.indexOf(":=");
|
int indexOfEqual = packet.indexOf(":=");
|
||||||
|
|
||||||
const uint8_t OFFSET = 3; // Offset for encoded data in the packet
|
const uint8_t OFFSET = 3; // Offset for encoded data in the packet
|
||||||
String GPSPacket;
|
String infoGPS;
|
||||||
if (indexOfExclamation > 10) {
|
if (indexOfExclamation > 10) {
|
||||||
GPSPacket = packet.substring(indexOfExclamation + OFFSET);
|
infoGPS = packet.substring(indexOfExclamation + OFFSET);
|
||||||
} else if (indexOfEqual > 10) {
|
} else if (indexOfEqual > 10) {
|
||||||
GPSPacket = packet.substring(indexOfEqual + OFFSET);
|
infoGPS = packet.substring(indexOfEqual + OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
String encodedLatitude = GPSPacket.substring(0,4);
|
float decodedLatitude = APRSPacketLib::decodeBase91EncodedLatitude(infoGPS.substring(0,4));
|
||||||
int Y1 = encodedLatitude[0] - 33;
|
float decodedLongitude = APRSPacketLib::decodeBase91EncodedLongitude(infoGPS.substring(4,8));
|
||||||
int Y2 = encodedLatitude[1] - 33;
|
|
||||||
int Y3 = encodedLatitude[2] - 33;
|
|
||||||
int Y4 = encodedLatitude[3] - 33;
|
|
||||||
float decodedLatitude = 90.0 - (((Y1 * pow(91,3)) + (Y2 * pow(91,2)) + (Y3 * 91) + Y4) / 380926.0);
|
|
||||||
|
|
||||||
String encodedLongitude = GPSPacket.substring(4,8);
|
return buildDistanceAndComment(decodedLatitude, decodedLongitude, infoGPS.substring(12));
|
||||||
int X1 = encodedLongitude[0] - 33;
|
|
||||||
int X2 = encodedLongitude[1] - 33;
|
|
||||||
int X3 = encodedLongitude[2] - 33;
|
|
||||||
int X4 = encodedLongitude[3] - 33;
|
|
||||||
float decodedLongitude = -180.0 + (((X1 * pow(91,3)) + (X2 * pow(91,2)) + (X3 * 91) + X4) / 190463.0);
|
|
||||||
|
|
||||||
distance = String(calculateDistanceTo(decodedLatitude, decodedLongitude),1);
|
|
||||||
|
|
||||||
String decodedGPS = String(decodedLatitude,5);
|
|
||||||
decodedGPS += "N / ";
|
|
||||||
decodedGPS += String(decodedLongitude,5);
|
|
||||||
decodedGPS += "E / ";
|
|
||||||
decodedGPS += distance;
|
|
||||||
decodedGPS += "km";
|
|
||||||
|
|
||||||
String comment = GPSPacket.substring(12);
|
|
||||||
if (comment != "") {
|
|
||||||
decodedGPS += " / ";
|
|
||||||
decodedGPS += comment;
|
|
||||||
}
|
|
||||||
return decodedGPS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getReceivedGPS(const String& packet) {
|
String getReceivedGPS(const String& packet) {
|
||||||
@@ -195,21 +133,7 @@ namespace GPS_Utils {
|
|||||||
convertedLongitude += Longitude.substring(Longitude.indexOf(".") + 1, Longitude.indexOf(".") + 3).toFloat() / (60*100);
|
convertedLongitude += Longitude.substring(Longitude.indexOf(".") + 1, Longitude.indexOf(".") + 3).toFloat() / (60*100);
|
||||||
if (Longitude.endsWith("W")) convertedLongitude = -convertedLongitude; // Handle Western Hemisphere
|
if (Longitude.endsWith("W")) convertedLongitude = -convertedLongitude; // Handle Western Hemisphere
|
||||||
|
|
||||||
distance = String(calculateDistanceTo(convertedLatitude, convertedLongitude),1);
|
return buildDistanceAndComment(convertedLatitude, convertedLongitude, infoGPS.substring(19));
|
||||||
|
|
||||||
String decodedGPS = String(convertedLatitude,5);
|
|
||||||
decodedGPS += "N / ";
|
|
||||||
decodedGPS += String(convertedLongitude,5);
|
|
||||||
decodedGPS += "E / ";
|
|
||||||
decodedGPS += distance;
|
|
||||||
decodedGPS += "km";
|
|
||||||
|
|
||||||
String comment = infoGPS.substring(19);
|
|
||||||
if (comment != "") {
|
|
||||||
decodedGPS += " / ";
|
|
||||||
decodedGPS += comment;
|
|
||||||
}
|
|
||||||
return decodedGPS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String getDistanceAndComment(const String& packet) {
|
String getDistanceAndComment(const String& packet) {
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ namespace LoRa_Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void changeFreqTx() {
|
void changeFreqTx() {
|
||||||
delay(500);
|
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);
|
||||||
@@ -138,7 +138,7 @@ namespace LoRa_Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void changeFreqRx() {
|
void changeFreqRx() {
|
||||||
delay(500);
|
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);
|
||||||
@@ -150,7 +150,7 @@ namespace LoRa_Utils {
|
|||||||
if (!Config.loramodule.txActive) return;
|
if (!Config.loramodule.txActive) return;
|
||||||
|
|
||||||
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
|
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
|
||||||
if (!packetIsBeacon || (packetIsBeacon && !Config.digi.beaconOnRxFreq)) {
|
if (!packetIsBeacon || (packetIsBeacon && Config.beacon.beaconFreq == 1)) {
|
||||||
changeFreqTx();
|
changeFreqTx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ namespace LoRa_Utils {
|
|||||||
if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, LOW); // disabled in Ultra Eco Mode
|
if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, LOW); // disabled in Ultra Eco Mode
|
||||||
#endif
|
#endif
|
||||||
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
|
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
|
||||||
if (!packetIsBeacon || (packetIsBeacon && !Config.digi.beaconOnRxFreq)) {
|
if (!packetIsBeacon || (packetIsBeacon && Config.beacon.beaconFreq == 1)) {
|
||||||
changeFreqRx();
|
changeFreqRx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ namespace LoRa_Utils {
|
|||||||
if (packet != "") {
|
if (packet != "") {
|
||||||
|
|
||||||
String sender = packet.substring(3, packet.indexOf(">"));
|
String sender = packet.substring(3, packet.indexOf(">"));
|
||||||
if (packet.substring(0,3) == "\x3c\xff\x01" && !STATION_Utils::isBlacklisted(sender)){ // avoid processing BlackListed stations
|
if (packet.substring(0,3) == "\x3c\xff\x01" && !STATION_Utils::isBlacklisted(sender)) { // avoid processing BlackListed stations
|
||||||
rssi = radio.getRSSI();
|
rssi = radio.getRSSI();
|
||||||
snr = radio.getSNR();
|
snr = radio.getSNR();
|
||||||
freqError = radio.getFrequencyError();
|
freqError = radio.getFrequencyError();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
extern Configuration Config;
|
extern Configuration Config;
|
||||||
|
|
||||||
WiFiUDP ntpUDP;
|
WiFiUDP ntpUDP;
|
||||||
NTPClient timeClient(ntpUDP, Config.ntp.server.c_str(), 0, 15 * 60 * 1000); // Update interval 15 min
|
NTPClient* timeClient;
|
||||||
|
|
||||||
|
|
||||||
namespace NTP_Utils {
|
namespace NTP_Utils {
|
||||||
@@ -35,17 +35,17 @@ namespace NTP_Utils {
|
|||||||
void setup() {
|
void setup() {
|
||||||
if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") {
|
if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") {
|
||||||
int gmt = Config.ntp.gmtCorrection * 3600;
|
int gmt = Config.ntp.gmtCorrection * 3600;
|
||||||
timeClient.setTimeOffset(gmt);
|
timeClient = new NTPClient(ntpUDP, Config.ntp.server.c_str(), gmt, 15 * 60 * 1000); // Update interval 15 min
|
||||||
timeClient.begin();
|
timeClient->begin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") timeClient.update();
|
if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") timeClient->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getFormatedTime() {
|
String getFormatedTime() {
|
||||||
if (Config.digi.ecoMode == 0) return timeClient.getFormattedTime();
|
if (Config.digi.ecoMode == 0) return timeClient->getFormattedTime();
|
||||||
return "DigiEcoMode Active";
|
return "DigiEcoMode Active";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ bool packetIsBeacon = false;
|
|||||||
|
|
||||||
namespace STATION_Utils {
|
namespace STATION_Utils {
|
||||||
|
|
||||||
std::vector<String> loadCallSignList(const String& list) {
|
std::vector<String> loadCallsignList(const String& list) {
|
||||||
std::vector<String> loadedList;
|
std::vector<String> loadedList;
|
||||||
|
|
||||||
String callsigns = list;
|
String callsigns = list;
|
||||||
@@ -77,12 +77,12 @@ namespace STATION_Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loadBlacklistAndManagers() {
|
void loadBlacklistAndManagers() {
|
||||||
blacklist = loadCallSignList(Config.blacklist);
|
blacklist = loadCallsignList(Config.blacklist);
|
||||||
managers = loadCallSignList(Config.remoteManagement.managers);
|
managers = loadCallsignList(Config.remoteManagement.managers);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkCallsignList(const std::vector<String>& list, const String& callsign) {
|
bool checkCallsignList(const std::vector<String>& list, const String& callsign) {
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (size_t i = 0; i < list.size(); i++) {
|
||||||
int wildcardIndex = list[i].indexOf("*");
|
int wildcardIndex = list[i].indexOf("*");
|
||||||
if (wildcardIndex >= 0) {
|
if (wildcardIndex >= 0) {
|
||||||
String wildcard = list[i].substring(0, wildcardIndex);
|
String wildcard = list[i].substring(0, wildcardIndex);
|
||||||
|
|||||||
@@ -21,12 +21,15 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "station_utils.h"
|
#include "station_utils.h"
|
||||||
#include "kiss_protocol.h"
|
#include "kiss_protocol.h"
|
||||||
|
#include "aprs_is_utils.h"
|
||||||
#include "kiss_utils.h"
|
#include "kiss_utils.h"
|
||||||
#include "tnc_utils.h"
|
#include "tnc_utils.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
extern Configuration Config;
|
extern Configuration Config;
|
||||||
|
extern WiFiClient aprsIsClient;
|
||||||
|
extern bool passcodeValid;
|
||||||
|
|
||||||
#define MAX_CLIENTS 4
|
#define MAX_CLIENTS 4
|
||||||
#define INPUT_BUFFER_SIZE (2 + MAX_CLIENTS)
|
#define INPUT_BUFFER_SIZE (2 + MAX_CLIENTS)
|
||||||
@@ -94,7 +97,8 @@ namespace TNC_Utils {
|
|||||||
String sender = frame.substring(0,frame.indexOf(">"));
|
String sender = frame.substring(0,frame.indexOf(">"));
|
||||||
|
|
||||||
if (Config.tnc.acceptOwn || sender != Config.callsign) {
|
if (Config.tnc.acceptOwn || sender != Config.callsign) {
|
||||||
STATION_Utils::addToOutputPacketBuffer(frame);
|
if (Config.loramodule.txActive) STATION_Utils::addToOutputPacketBuffer(frame);
|
||||||
|
if (Config.tnc.aprsBridgeActive && Config.aprs_is.active && passcodeValid && aprsIsClient.connected()) APRS_IS_Utils::upload(frame);
|
||||||
} else {
|
} else {
|
||||||
Utils::println("Ignored own frame from KISS");
|
Utils::println("Ignored own frame from KISS");
|
||||||
}
|
}
|
||||||
@@ -131,8 +135,8 @@ namespace TNC_Utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendToClients(const String& packet) {
|
void sendToClients(const String& packet, bool stripBytes) {
|
||||||
String cleanPacket = packet.substring(3);
|
String cleanPacket = stripBytes ? packet.substring(3): packet;
|
||||||
|
|
||||||
const String kissEncoded = encodeKISS(cleanPacket);
|
const String kissEncoded = encodeKISS(cleanPacket);
|
||||||
|
|
||||||
@@ -152,8 +156,8 @@ namespace TNC_Utils {
|
|||||||
Utils::println(cleanPacket);
|
Utils::println(cleanPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendToSerial(const String& packet) {
|
void sendToSerial(const String& packet, bool stripBytes) {
|
||||||
String cleanPacket = packet.substring(3);
|
String cleanPacket = stripBytes ? packet.substring(3): packet;
|
||||||
Serial.print(encodeKISS(cleanPacket));
|
Serial.print(encodeKISS(cleanPacket));
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
|
* along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <APRSPacketLib.h>
|
||||||
#include <TinyGPS++.h>
|
#include <TinyGPS++.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include "telemetry_utils.h"
|
#include "telemetry_utils.h"
|
||||||
@@ -71,12 +72,8 @@ String secondaryBeaconPacket;
|
|||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
void processStatus() {
|
void processStatus() {
|
||||||
String status = Config.callsign;
|
String status = APRSPacketLib::generateBasePacket(Config.callsign, "APLRG1", Config.beacon.path);
|
||||||
status.concat(">APLRG1");
|
|
||||||
if (Config.beacon.path.indexOf("WIDE") == 0) {
|
|
||||||
status.concat(",");
|
|
||||||
status.concat(Config.beacon.path);
|
|
||||||
}
|
|
||||||
if (WiFi.status() == WL_CONNECTED && Config.aprs_is.active && Config.beacon.sendViaAPRSIS) {
|
if (WiFi.status() == WL_CONNECTED && Config.aprs_is.active && Config.beacon.sendViaAPRSIS) {
|
||||||
delay(1000);
|
delay(1000);
|
||||||
status.concat(",qAC:>");
|
status.concat(",qAC:>");
|
||||||
@@ -161,18 +158,27 @@ namespace Utils {
|
|||||||
|
|
||||||
showActiveStations();
|
showActiveStations();
|
||||||
|
|
||||||
beaconPacket = iGateBeaconPacket;
|
|
||||||
secondaryBeaconPacket = iGateLoRaBeaconPacket;
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
if (Config.beacon.gpsActive && Config.digi.ecoMode == 0) {
|
if (Config.beacon.gpsActive && Config.digi.ecoMode == 0) {
|
||||||
GPS_Utils::getData();
|
GPS_Utils::getData();
|
||||||
if (gps.location.isUpdated() && gps.location.lat() != 0.0 && gps.location.lng() != 0.0) {
|
if (gps.location.isUpdated() && gps.location.lat() != 0.0 && gps.location.lng() != 0.0) {
|
||||||
GPS_Utils::generateBeaconFirstPart();
|
String basePacket = APRSPacketLib::generateBasePacket(Config.callsign, "APLRG1", Config.beacon.path);
|
||||||
String encodedGPS = GPS_Utils::encodeGPS(gps.location.lat(), gps.location.lng(), Config.beacon.overlay, Config.beacon.symbol);
|
String encodedGPS = APRSPacketLib::encodeGPSIntoBase91(gps.location.lat(),gps.location.lng(), 0, 0, Config.beacon.symbol, false, 0, true, Config.beacon.ambiguityLevel);
|
||||||
beaconPacket = iGateBeaconPacket + encodedGPS;
|
|
||||||
secondaryBeaconPacket = iGateLoRaBeaconPacket + encodedGPS;
|
beaconPacket = basePacket;
|
||||||
|
beaconPacket += ",qAC:!";
|
||||||
|
beaconPacket += Config.beacon.overlay;
|
||||||
|
beaconPacket += encodedGPS;
|
||||||
|
|
||||||
|
secondaryBeaconPacket = basePacket;
|
||||||
|
secondaryBeaconPacket += ":=";
|
||||||
|
secondaryBeaconPacket += Config.beacon.overlay;
|
||||||
|
secondaryBeaconPacket += encodedGPS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
beaconPacket = iGateBeaconPacket;
|
||||||
|
secondaryBeaconPacket = iGateLoRaBeaconPacket;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Config.wxsensor.active) {
|
if (Config.wxsensor.active) {
|
||||||
@@ -284,6 +290,7 @@ namespace Utils {
|
|||||||
Serial.println("Tx Freq less than 125kHz from Rx Freq ---> NOT VALID");
|
Serial.println("Tx Freq less than 125kHz from Rx Freq ---> NOT VALID");
|
||||||
displayShow("Tx Freq is less than ", "125kHz from Rx Freq", "device will autofix", "and then reboot", 1000);
|
displayShow("Tx Freq is less than ", "125kHz from Rx Freq", "device will autofix", "and then reboot", 1000);
|
||||||
Config.loramodule.txFreq = Config.loramodule.rxFreq; // Inform about that but then change the TX QRG to RX QRG and reset the device
|
Config.loramodule.txFreq = Config.loramodule.rxFreq; // Inform about that but then change the TX QRG to RX QRG and reset the device
|
||||||
|
Config.beacon.beaconFreq = 1; // return to LoRa Tx Beacon Freq
|
||||||
Config.writeFile();
|
Config.writeFile();
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
@@ -401,6 +408,7 @@ namespace Utils {
|
|||||||
cleanCallsign = callsign.substring(0, callsign.indexOf("-"));
|
cleanCallsign = callsign.substring(0, callsign.indexOf("-"));
|
||||||
String ssid = callsign.substring(callsign.indexOf("-") + 1);
|
String ssid = callsign.substring(callsign.indexOf("-") + 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;
|
||||||
for (int i = 0; i < ssid.length(); i++) {
|
for (int i = 0; i < ssid.length(); i++) {
|
||||||
if (!isAlphaNumeric(ssid[i])) return false;
|
if (!isAlphaNumeric(ssid[i])) return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ namespace WEB_Utils {
|
|||||||
Config.beacon.interval = getParamIntSafe("beacon.interval", Config.beacon.interval);
|
Config.beacon.interval = getParamIntSafe("beacon.interval", Config.beacon.interval);
|
||||||
Config.beacon.sendViaAPRSIS = request->hasParam("beacon.sendViaAPRSIS", true);
|
Config.beacon.sendViaAPRSIS = request->hasParam("beacon.sendViaAPRSIS", true);
|
||||||
Config.beacon.sendViaRF = request->hasParam("beacon.sendViaRF", true);
|
Config.beacon.sendViaRF = request->hasParam("beacon.sendViaRF", true);
|
||||||
|
Config.beacon.beaconFreq = getParamIntSafe("beacon.beaconFreq", Config.beacon.beaconFreq);
|
||||||
Config.beacon.latitude = getParamDoubleSafe("beacon.latitude", Config.beacon.latitude);
|
Config.beacon.latitude = getParamDoubleSafe("beacon.latitude", Config.beacon.latitude);
|
||||||
Config.beacon.longitude = getParamDoubleSafe("beacon.longitude", Config.beacon.longitude);
|
Config.beacon.longitude = getParamDoubleSafe("beacon.longitude", Config.beacon.longitude);
|
||||||
Config.beacon.comment = getParamStringSafe("beacon.comment", Config.beacon.comment);
|
Config.beacon.comment = getParamStringSafe("beacon.comment", Config.beacon.comment);
|
||||||
@@ -190,7 +191,7 @@ namespace WEB_Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Config.beacon.gpsActive = request->hasParam("beacon.gpsActive", true);
|
Config.beacon.gpsActive = request->hasParam("beacon.gpsActive", true);
|
||||||
Config.beacon.gpsAmbiguity = request->hasParam("beacon.gpsAmbiguity", true);
|
Config.beacon.ambiguityLevel = getParamIntSafe("beacon.ambiguityLevel", Config.beacon.ambiguityLevel);
|
||||||
|
|
||||||
Config.personalNote = getParamStringSafe("personalNote", Config.personalNote);
|
Config.personalNote = getParamStringSafe("personalNote", Config.personalNote);
|
||||||
|
|
||||||
@@ -198,9 +199,8 @@ 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.beaconOnRxFreq = request->hasParam("digi.beaconOnRxFreq", 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);
|
||||||
Config.loramodule.rxSpreadingFactor = getParamIntSafe("lora.rxSpreadingFactor", Config.loramodule.rxSpreadingFactor);
|
Config.loramodule.rxSpreadingFactor = getParamIntSafe("lora.rxSpreadingFactor", Config.loramodule.rxSpreadingFactor);
|
||||||
@@ -259,6 +259,7 @@ namespace WEB_Utils {
|
|||||||
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.mqtt.active = request->hasParam("mqtt.active", true);
|
Config.mqtt.active = request->hasParam("mqtt.active", true);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace WIFI_Utils {
|
|||||||
Serial.print(millis());
|
Serial.print(millis());
|
||||||
Serial.println("Reconnecting to WiFi...");
|
Serial.println("Reconnecting to WiFi...");
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
WIFI_Utils::startWiFi();//WiFi.reconnect();
|
WIFI_Utils::startWiFi();
|
||||||
previousWiFiMillis = millis();
|
previousWiFiMillis = millis();
|
||||||
|
|
||||||
if (Config.backupDigiMode) {
|
if (Config.backupDigiMode) {
|
||||||
|
|||||||