Compare commits

..

55 Commits

Author SHA1 Message Date
richonguzman 2625e7b91d update readme v314 2025-10-15 17:29:26 -03:00
richonguzman 75337d6c29 update to Tnc strip bytes 2025-10-15 17:12:38 -03:00
richonguzman a618383617 APRS Bridge for TNC 2025-10-15 15:11:07 -03:00
richonguzman 8add599838 NTP server change fix 2025-10-15 14:31:02 -03:00
richonguzman 83ec2265c6 Rx and Tx Freq selection fix 2025-10-15 14:18:43 -03:00
richonguzman bec4f4f473 beaconOnRxFreq into beacon config 2025-10-15 10:58:30 -03:00
richonguzman 87a67cd2c9 readmeupdate otro mas 2025-10-13 13:29:56 -03:00
richonguzman 4e48b2d02d manual update 2025-10-13 13:11:51 -03:00
richonguzman 607277bfe9 readme update2 2025-10-13 12:44:47 -03:00
richonguzman c2f8596667 readme update 2025-10-13 12:44:15 -03:00
richonguzman ba7ff2a2d9 WebUI change 2025-10-13 12:38:52 -03:00
richonguzman b44eb1028d no more speed standards on index 2025-10-13 02:03:18 -03:00
richonguzman d7602268f2 changes for Rx and Tx Lora Freq 2025-10-13 02:00:05 -03:00
richonguzman 2f6f9be28e Lora Config separated for Rx and Tx 2025-10-13 01:33:41 -03:00
richonguzman 92572245cd beacon Freq on digi mod 2025-10-12 21:45:23 -03:00
richonguzman 152217e71c startup delay added 2025-10-12 14:21:51 -03:00
richonguzman d334164b6f Beacon Freq on Digi Mode 2025-10-11 18:27:06 -03:00
richonguzman 61409ce683 index correction 2025-10-11 15:57:29 -03:00
richonguzman 742a6b6477 readme update 2025-10-11 13:23:39 -03:00
richonguzman dd2fce3908 igate beacon over mqtt 2025-10-11 13:22:08 -03:00
richonguzman 90b29b66d5 callsign trim 2025-10-11 12:50:53 -03:00
richonguzman 2a86cdb0d8 Op ntp server 2025-10-11 12:40:07 -03:00
richonguzman 1abaa299e0 update readme 2025-10-10 12:44:15 -03:00
Ricardo Guzman (Richonguzman) 9cbd7c22fd Merge pull request #342 from richonguzman/richonguzman-patch-14
Update README.md
2025-10-10 12:15:18 -03:00
Ricardo Guzman (Richonguzman) e15e6def91 Update README.md 2025-10-10 12:14:56 -03:00
richonguzman 33c8be4f48 added manual for 3.1.2 2025-10-10 12:11:24 -03:00
Ricardo Guzman (Richonguzman) c2a7c26d78 Merge pull request #341 from richonguzman/richonguzman-patch-13
Update README.md
2025-10-10 12:08:41 -03:00
Ricardo Guzman (Richonguzman) 387e8a988a Update README.md 2025-10-10 12:08:28 -03:00
Ricardo Guzman (Richonguzman) 48b075a554 Merge pull request #340 from richonguzman/richonguzman-patch-12
Update README.md
2025-10-10 12:06:38 -03:00
Ricardo Guzman (Richonguzman) 7e76e43817 Update README.md 2025-10-10 12:06:25 -03:00
Ricardo Guzman (Richonguzman) 9b7b4e1838 Merge pull request #339 from richonguzman/richonguzman-patch-11
Update README.md
2025-10-10 12:04:17 -03:00
Ricardo Guzman (Richonguzman) 5b9d56843b Update README.md 2025-10-10 12:04:04 -03:00
Ricardo Guzman (Richonguzman) 30eb1023dc Merge pull request #338 from richonguzman/richonguzman-patch-10
Update README.md
2025-10-10 12:03:09 -03:00
Ricardo Guzman (Richonguzman) 1ba86af61b Update README.md 2025-10-10 12:02:54 -03:00
Ricardo Guzman (Richonguzman) 1d475bc8a2 Merge pull request #337 from richonguzman/richonguzman-patch-9
Update README.md
2025-10-10 11:58:13 -03:00
Ricardo Guzman (Richonguzman) 70f9a6fa04 Update README.md 2025-10-10 11:57:50 -03:00
Ricardo Guzman (Richonguzman) 6747511850 Merge pull request #336 from richonguzman/richonguzman-patch-8
Update README.md
2025-10-10 11:56:25 -03:00
Ricardo Guzman (Richonguzman) 96a4394e89 Update README.md 2025-10-10 11:56:10 -03:00
Ricardo Guzman (Richonguzman) 4e009bc14c Merge pull request #332 from richonguzman/richonguzman-patch-7
adding heltec wireless bridge
2025-09-29 15:52:00 -03:00
Ricardo Guzman (Richonguzman) 4c11c66a1c adding heltec wireless bridge 2025-09-29 15:51:41 -03:00
richonguzman a89181b5df update complete 2025-09-26 11:37:02 -03:00
richonguzman 9a94a193f9 update before release 2025-09-25 22:01:38 -03:00
richonguzman 9c7f6c7934 led update 2025-09-25 17:54:53 -03:00
richonguzman 53e8941262 blue led add 2025-09-25 17:33:59 -03:00
richonguzman 60a148d362 testing1 2025-09-25 15:55:18 -03:00
richonguzman 36cd1578cc adding basic stuff 2025-09-25 15:50:28 -03:00
richonguzman c3036f290f TCPIP correction 2025-09-25 15:35:38 -03:00
richonguzman 8eb4ef1dc2 testeando ultimos valores 2025-09-17 17:00:49 -03:00
richonguzman d5930380b4 testing new config init validation 2025-09-17 16:53:09 -03:00
richonguzman e42f4b59ed prueba nueva web write desde formulario 2025-09-17 15:29:13 -03:00
richonguzman 2697f2a5f2 update a configuration cpp 2025-09-17 14:29:37 -03:00
richonguzman 36c970aed9 json file size fix 2025-09-14 20:00:56 -03:00
richonguzman 10e1581bc2 new board 2025-09-14 19:54:20 -03:00
Ricardo Guzman (Richonguzman) bc57d1609a Merge pull request #321 from richonguzman/richonguzman-patch-6
Update README.md
2025-09-09 10:22:52 -03:00
Ricardo Guzman (Richonguzman) 37380c6b9d Update README.md 2025-09-09 10:22:27 -03:00
58 changed files with 1115 additions and 698 deletions
+2
View File
@@ -29,6 +29,8 @@ jobs:
chip: esp32s3 chip: esp32s3
- name: heltec_wireless_stick_lite_v3_display - name: heltec_wireless_stick_lite_v3_display
chip: esp32s3 chip: esp32s3
- name: heltec_wireless_bridge
chip: esp32
- name: ESP32_DIY_LoRa - name: ESP32_DIY_LoRa
chip: esp32 chip: esp32
- name: ESP32_DIY_LoRa_915 - name: ESP32_DIY_LoRa_915
+22 -23
View File
@@ -9,46 +9,38 @@ __(This iGate Firmware works with all LoRa Tracker Firmwares (specially this <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>
____________________________________________________
## 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/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)
<br />
# WEB FLASHER/INSTALLER is <a href="https://richonguzman.github.io/lora-igate-web-flasher/installer.html" target="_blank">here</a>
____________________________________________________ ____________________________________________________
# WIKI ## SUPPORTED BOARDS (<a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/Supported-Boards-and-Buying-Links" target="_blank">Buying links</a>).
### FAQ, BME280, TNC and more --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/00.-FAQ-(frequently-asked-questions)" target="_blank">here</a>.
### Installation Guide --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/01.-Installation-Guide" target="_blank">here</a>.
<br />
# SUPPORTED BOARDS
### Buying links --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/108.-Supported-Boards-and-Buying-Links" target="_blank">here</a>.
(NOTE: all boards with 433-868-915 MHz versions) (NOTE: all boards with 433-868-915 MHz versions)
- TTGO Lilygo LoRa32 T3S3 V1.2 and LoRa32 V2.1 (V1.6 is the same). - TTGO Lilygo LoRa32 T3S3 V1.2 and LoRa32 V2.1 (V1.6 is the same).
- TTGO T-Beam V1.0 , V1.1, V1.2 (also variations with SX1262 and SX1268 LoRa Modules). - TTGO T-Beam V1.0 , V1.1, V1.2 (also variations with SX1262 and SX1268 LoRa Modules) and Supreme V3.
- 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(19003) - RAK Wireless 4631 + 19007(or 19003)
- Faketec (NRF52840 + Heltec HTRA62(SX1262)) - Faketec V3 (NRF52840 + Heltec HTRA62(SX1262))
- QRP Labs LightGateway 1.0 and Plus 1.0. - QRP Labs LightGateway 1.0 and Plus 1.0.
- Faketec V3 (NRF52840 + Heltec HTRA62 SX1262) - ESP32 + SX1278 LoRa Module or Ebyte 400M30S (or 900M30S) 1W LoRa Module for a DIY Versions.
- ESP32 Wroom + SX1278 LoRa Module or Ebyte 400M30S (or 900M30S) 1W LoRa Module for a DIY Versions.
- ESP32C3 + Ebyte 400M30S(or 900M30S) 1W LoRa Module for another DIY version. - ESP32C3 + Ebyte 400M30S(or 900M30S) 1W LoRa Module for another DIY version.
@@ -58,8 +50,15 @@ ____________________________________________________
<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-10 Converted the Wiki into a PDF manual.
- 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-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).
- 2025-06-20 New Boards Added: Heltec T114 MeshNode, Faketec V3 as Digipeaters and QRP Labs LightGateway Plus 1.0. - 2025-06-20 New Boards Added: Heltec T114 MeshNode, Faketec V3 as Digipeaters and QRP Labs LightGateway Plus 1.0.
- 2025-06-19 DateVersion format Change. Licence changed into GNU GPLv3. - 2025-06-19 DateVersion format Change. Licence changed into GNU GPLv3.
+17 -9
View File
@@ -17,6 +17,7 @@
"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,
@@ -38,14 +39,17 @@
"ecoMode": 0 "ecoMode": 0
}, },
"lora": { "lora": {
"txFreq": 433775000, "rxActive": true,
"rxFreq": 433775000, "rxFreq": 433775000,
"spreadingFactor": 12, "rxSpreadingFactor": 12,
"signalBandwidth": 125000, "rxCodingRate4": 5,
"codingRate4": 5, "rxSignalBandwidth": 125000,
"power": 20,
"txActive": false, "txActive": false,
"rxActive": true "txFreq": 433775000,
"txSpreadingFactor": 12,
"txCodingRate4": 5,
"txSignalBandwidth": 125000,
"power": 20
}, },
"display": { "display": {
"alwaysOn": true, "alwaysOn": true,
@@ -78,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,
@@ -86,7 +91,8 @@
"topic": "", "topic": "",
"username": "", "username": "",
"password": "", "password": "",
"port": 1883 "port": 1883,
"beaconOverMqtt": false
}, },
"ota": { "ota": {
"username": "", "username": "",
@@ -101,12 +107,14 @@
"rfOnly": true "rfOnly": true
}, },
"ntp": { "ntp": {
"server": "pool.ntp.org",
"gmtCorrection": 0.0 "gmtCorrection": 0.0
}, },
"other": { "other": {
"rememberStationTime": 30, "rememberStationTime": 30,
"backupDigiMode": false, "backupDigiMode": false,
"rebootMode": false, "rebootMode": false,
"rebootModeTime": 6 "rebootModeTime": 6,
"startupDelay": 0
} }
} }
+439 -335
View File
File diff suppressed because it is too large Load Diff
+32 -72
View File
@@ -95,6 +95,7 @@ function loadSettings(settings) {
networksContainer.appendChild(networkElement); networksContainer.appendChild(networkElement);
networkCount++; networkCount++;
}); });
document.getElementById("startupDelay").value = settings.startupDelay;
// APRS-IS // APRS-IS
document.getElementById("aprs_is.active").checked = settings.aprs_is.active; document.getElementById("aprs_is.active").checked = settings.aprs_is.active;
@@ -118,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;
@@ -136,13 +141,16 @@ function loadSettings(settings) {
document.getElementById("digi.ecoMode").value = settings.digi.ecoMode; document.getElementById("digi.ecoMode").value = settings.digi.ecoMode;
// LoRa // LoRa
document.getElementById("lora.txFreq").value = settings.lora.txFreq;
document.getElementById("lora.rxFreq").value = settings.lora.rxFreq;
document.getElementById("lora.txActive").checked = settings.lora.txActive;
document.getElementById("lora.rxActive").checked = settings.lora.rxActive; document.getElementById("lora.rxActive").checked = settings.lora.rxActive;
document.getElementById("lora.spreadingFactor").value = settings.lora.spreadingFactor; document.getElementById("lora.rxFreq").value = settings.lora.rxFreq;
document.getElementById("lora.signalBandwidth").value = settings.lora.signalBandwidth; document.getElementById("lora.rxSpreadingFactor").value = settings.lora.rxSpreadingFactor;
document.getElementById("lora.codingRate4").value = settings.lora.codingRate4; document.getElementById("lora.rxCodingRate4").value = settings.lora.rxCodingRate4;
document.getElementById("lora.rxSignalBandwidth").value = settings.lora.rxSignalBandwidth;
document.getElementById("lora.txActive").checked = settings.lora.txActive;
document.getElementById("lora.txFreq").value = settings.lora.txFreq;
document.getElementById("lora.txSpreadingFactor").value = settings.lora.txSpreadingFactor;
document.getElementById("lora.txCodingRate4").value = settings.lora.txCodingRate4;
document.getElementById("lora.txSignalBandwidth").value = settings.lora.txSignalBandwidth;
document.getElementById("lora.power").value = settings.lora.power; document.getElementById("lora.power").value = settings.lora.power;
// Display // Display
@@ -198,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
@@ -207,12 +216,14 @@ 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;
MqttCheckbox.checked = settings.mqtt.active; document.getElementById("mqtt.beaconOverMqtt").value = settings.mqtt.beaconOverMqtt;
MqttServer.disabled = !MqttCheckbox.check; MqttCheckbox.checked = settings.mqtt.active;
MqttTopic.disabled = !MqttCheckbox.check; MqttServer.disabled = !MqttCheckbox.check;
MqttUsername.disabled = !MqttCheckbox.check; MqttTopic.disabled = !MqttCheckbox.check;
MqttPassword.disabled = !MqttCheckbox.check; MqttUsername.disabled = !MqttCheckbox.check;
MqttPort.disabled = !MqttCheckbox.check; MqttPassword.disabled = !MqttCheckbox.check;
MqttPort.disabled = !MqttCheckbox.check;
MqttBeaconOverMqtt.disabled = !MqttCheckbox.check;
// Reboot // Reboot
document.getElementById("other.rebootMode").checked = settings.other.rebootMode; document.getElementById("other.rebootMode").checked = settings.other.rebootMode;
@@ -241,13 +252,13 @@ function loadSettings(settings) {
document.getElementById("remoteManagement.rfOnly").checked = settings.remoteManagement.rfOnly; document.getElementById("remoteManagement.rfOnly").checked = settings.remoteManagement.rfOnly;
// NTP // NTP
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 // Experimental
document.getElementById("other.backupDigiMode").checked = settings.other.backupDigiMode; document.getElementById("other.backupDigiMode").checked = settings.other.backupDigiMode;
updateImage(); updateImage();
refreshSpeedStandard();
} }
function showToast(message) { function showToast(message) {
@@ -299,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"]');
@@ -379,12 +396,14 @@ const MqttTopic = document.querySelector('input[name="mqtt.topic
const MqttUsername = document.querySelector('input[name="mqtt.username"]'); const MqttUsername = document.querySelector('input[name="mqtt.username"]');
const MqttPassword = document.querySelector('input[name="mqtt.password"]'); const MqttPassword = document.querySelector('input[name="mqtt.password"]');
const MqttPort = document.querySelector('input[name="mqtt.port"]'); const MqttPort = document.querySelector('input[name="mqtt.port"]');
const MqttBeaconOverMqtt = document.querySelector('input[name="mqtt.beaconOverMqtt"]');
MqttCheckbox.addEventListener("change", function () { MqttCheckbox.addEventListener("change", function () {
MqttServer.disabled = !this.checked; MqttServer.disabled = !this.checked;
MqttTopic.disabled = !this.checked; MqttTopic.disabled = !this.checked;
MqttUsername.disabled = !this.checked; MqttUsername.disabled = !this.checked;
MqttPassword.disabled = !this.checked; MqttPassword.disabled = !this.checked;
MqttPort.disabled = !this.checked; MqttPort.disabled = !this.checked;
MqttBeaconOverMqtt.disabled = !this.checked;
}); });
// Reboot Switches // Reboot Switches
@@ -451,65 +470,6 @@ document
updateImage(); updateImage();
}); });
const speedStandards = {
300: [125, 5, 12],
244: [125, 6, 12],
209: [125, 7, 12],
183: [125, 8, 12],
610: [125, 8, 10],
1200: [125, 7, 9],
};
function refreshSpeedStandard() {
const bw = Number(document.getElementById("lora.signalBandwidth").value);
const cr4 = Number(document.getElementById("lora.codingRate4").value);
const sf = Number(document.getElementById("lora.spreadingFactor").value);
let found = false;
for (const speed in speedStandards) {
const standard = speedStandards[speed];
if (standard[0] !== bw / 1000) continue;
if (standard[1] !== cr4) continue;
if (standard[2] !== sf) continue;
document.getElementById("action.speed").value = speed;
found = true;
break;
}
if (!found) {
document.getElementById("action.speed").value = "";
}
}
document
.getElementById("lora.signalBandwidth")
.addEventListener("focusout", refreshSpeedStandard);
document
.getElementById("lora.codingRate4")
.addEventListener("focusout", refreshSpeedStandard);
document
.getElementById("lora.spreadingFactor")
.addEventListener("focusout", refreshSpeedStandard);
document.getElementById("action.speed").addEventListener("change", function () {
const speed = document.getElementById("action.speed").value;
if (speed !== "") {
const value = speedStandards[Number(speed)];
const bw = value[0];
const cr4 = value[1];
const sf = value[2];
document.getElementById("lora.signalBandwidth").value = bw * 1000;
document.getElementById("lora.codingRate4").value = cr4;
document.getElementById("lora.spreadingFactor").value = sf;
}
});
const form = document.querySelector("form"); const form = document.querySelector("form");
Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 711 KiB

+20 -12
View File
@@ -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;
bool gpsAmbiguity;
}; };
class APRS_IS { class APRS_IS {
@@ -67,18 +68,21 @@ 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)
}; };
class LoraModule { class LoraModule {
public: public:
long txFreq;
long rxFreq;
bool txActive;
bool rxActive; bool rxActive;
int spreadingFactor; long rxFreq;
long signalBandwidth; int rxSpreadingFactor;
int codingRate4; int rxCodingRate4;
long rxSignalBandwidth;
bool txActive;
long txFreq;
int txSpreadingFactor;
int txCodingRate4;
long txSignalBandwidth;
int power; int power;
}; };
@@ -123,6 +127,7 @@ public:
bool enableServer; bool enableServer;
bool enableSerial; bool enableSerial;
bool acceptOwn; bool acceptOwn;
bool aprsBridgeActive;
}; };
class OTA { class OTA {
@@ -140,6 +145,7 @@ public:
class NTP { class NTP {
public: public:
String server;
float gmtCorrection; float gmtCorrection;
}; };
@@ -157,6 +163,7 @@ public:
String username; String username;
String password; String password;
int port; int port;
bool beaconOverMqtt;
}; };
class Configuration { class Configuration {
@@ -166,6 +173,7 @@ public:
bool backupDigiMode; bool backupDigiMode;
bool rebootMode; bool rebootMode;
int rebootModeTime; int rebootModeTime;
int startupDelay;
String personalNote; String personalNote;
String blacklist; String blacklist;
std::vector<WiFi_AP> wifiAPs; std::vector<WiFi_AP> wifiAPs;
@@ -185,8 +193,8 @@ public:
REMOTE_MANAGEMENT remoteManagement; REMOTE_MANAGEMENT remoteManagement;
MQTT mqtt; MQTT mqtt;
void init(); void setDefaultValues();
void writeFile(); bool writeFile();
Configuration(); Configuration();
private: private:
+1 -7
View File
@@ -23,12 +23,6 @@
#include <Arduino.h> #include <Arduino.h>
struct Packet25SegBuffer {
uint32_t receivedTime;
String station;
String payload;
};
struct LastHeardStation { struct LastHeardStation {
uint32_t lastHeardTime; uint32_t lastHeardTime;
String station; String station;
@@ -47,7 +41,7 @@ namespace STATION_Utils {
bool check25SegBuffer(const String& station, const String& textMessage); bool check25SegBuffer(const String& station, const String& textMessage);
void processOutputPacketBufferUltraEcoMode(); void processOutputPacketBufferUltraEcoMode();
void processOutputPacketBuffer(); void processOutputPacketBuffer();
void addToOutputPacketBuffer(const String& packet); void addToOutputPacketBuffer(const String& packet, bool flag = false);
} }
+2 -2
View File
@@ -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);
} }
+2 -1
View File
@@ -35,7 +35,7 @@ namespace Utils {
void processStatus(); void processStatus();
String getLocalIP(); String getLocalIP();
void setupDisplay(); void setupDisplay();
void activeStations(); void showActiveStations();
void checkBeaconInterval(); void checkBeaconInterval();
void checkDisplayInterval(); void checkDisplayInterval();
void validateFreqs(); void validateFreqs();
@@ -46,6 +46,7 @@ namespace Utils {
void checkRebootTime(); void checkRebootTime();
void checkSleepByLowBatteryVoltage(uint8_t mode); void checkSleepByLowBatteryVoltage(uint8_t mode);
bool checkValidCallsign(const String& callsign); bool checkValidCallsign(const String& callsign);
void startupDelay();
} }
Binary file not shown.
+7 -13
View File
@@ -33,7 +33,7 @@
Ricardo Guzman - CA2RXU Ricardo Guzman - CA2RXU
https://github.com/richonguzman/LoRa_APRS_iGate https://github.com/richonguzman/LoRa_APRS_iGate
(donations : http://paypal.me/richonguzman) (donations : http://paypal.me/richonguzman)
___________________________________________________________________*/ ___________________________________________________________________*/
@@ -67,8 +67,8 @@ ___________________________________________________________________*/
#endif #endif
String versionDate = "2025-09-09"; String versionDate = "2025-10-15";
String versionNumber = "3.1"; String versionNumber = "3.1.4";
Configuration Config; Configuration Config;
WiFiClient aprsIsClient; WiFiClient aprsIsClient;
WiFiClient mqttClient; WiFiClient mqttClient;
@@ -97,7 +97,6 @@ bool modemLoggedToAPRSIS = false;
std::vector<ReceivedPacket> receivedPackets; std::vector<ReceivedPacket> receivedPackets;
String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine; String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine;
//#define STARTUP_DELAY 5 //min
void setup() { void setup() {
@@ -108,12 +107,7 @@ void setup() {
Utils::validateFreqs(); Utils::validateFreqs();
GPS_Utils::setup(); GPS_Utils::setup();
STATION_Utils::loadBlacklistAndManagers(); STATION_Utils::loadBlacklistAndManagers();
Utils::startupDelay();
#ifdef STARTUP_DELAY // (TEST) just to wait for WiFi init of Routers
displayShow("", " STARTUP DELAY ...", "", "", 0);
delay(STARTUP_DELAY * 60 * 1000);
#endif
SLEEP_Utils::setup(); SLEEP_Utils::setup();
WIFI_Utils::setup(); WIFI_Utils::setup();
NTP_Utils::setup(); NTP_Utils::setup();
@@ -198,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
+5
View File
@@ -25,6 +25,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"
@@ -367,6 +368,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
}
} }
} }
+242 -118
View File
@@ -26,138 +26,158 @@
bool shouldSleepStop = true; bool shouldSleepStop = true;
void Configuration::writeFile() { bool Configuration::writeFile() {
Serial.println("Saving config..."); Serial.println("Saving configuration...");
StaticJsonDocument<2560> data; StaticJsonDocument<3584> data;
File configFile = SPIFFS.open("/igate_conf.json", "w"); File configFile = SPIFFS.open("/igate_conf.json", "w");
if (wifiAPs[0].ssid != "") { // We don't want to save Auto AP empty SSID if (!configFile) {
for (int i = 0; i < wifiAPs.size(); i++) { Serial.println("Error: Could not open config file for writing");
data["wifi"]["AP"][i]["ssid"] = wifiAPs[i].ssid; return false;
data["wifi"]["AP"][i]["password"] = wifiAPs[i].password;
}
} }
try {
data["wifi"]["autoAP"]["password"] = wifiAutoAP.password; if (wifiAPs[0].ssid != "") { // We don't want to save Auto AP empty SSID
data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout; for (int i = 0; i < wifiAPs.size(); i++) {
data["wifi"]["AP"][i]["ssid"] = wifiAPs[i].ssid;
data["wifi"]["AP"][i]["password"] = wifiAPs[i].password;
}
}
data["callsign"] = callsign; data["other"]["startupDelay"] = startupDelay;
data["aprs_is"]["active"] = aprs_is.active; data["wifi"]["autoAP"]["password"] = wifiAutoAP.password;
data["aprs_is"]["passcode"] = aprs_is.passcode; data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout;
data["aprs_is"]["server"] = aprs_is.server;
data["aprs_is"]["port"] = aprs_is.port;
data["aprs_is"]["filter"] = aprs_is.filter;
data["aprs_is"]["messagesToRF"] = aprs_is.messagesToRF;
data["aprs_is"]["objectsToRF"] = aprs_is.objectsToRF;
data["beacon"]["comment"] = beacon.comment; callsign.trim();
data["beacon"]["interval"] = beacon.interval; callsign.toUpperCase();
data["beacon"]["latitude"] = beacon.latitude; data["callsign"] = callsign;
data["beacon"]["longitude"] = beacon.longitude;
data["beacon"]["overlay"] = beacon.overlay;
data["beacon"]["symbol"] = beacon.symbol;
data["beacon"]["sendViaAPRSIS"] = beacon.sendViaAPRSIS;
data["beacon"]["sendViaRF"] = beacon.sendViaRF;
data["beacon"]["path"] = beacon.path;
data["beacon"]["statusActive"] = beacon.statusActive; data["aprs_is"]["active"] = aprs_is.active;
data["beacon"]["statusPacket"] = beacon.statusPacket; data["aprs_is"]["passcode"] = aprs_is.passcode;
data["aprs_is"]["server"] = aprs_is.server;
data["aprs_is"]["port"] = aprs_is.port;
data["aprs_is"]["filter"] = aprs_is.filter;
data["aprs_is"]["messagesToRF"] = aprs_is.messagesToRF;
data["aprs_is"]["objectsToRF"] = aprs_is.objectsToRF;
data["beacon"]["gpsActive"] = beacon.gpsActive; data["beacon"]["comment"] = beacon.comment;
data["beacon"]["gpsAmbiguity"] = beacon.gpsAmbiguity; data["beacon"]["interval"] = beacon.interval;
data["beacon"]["latitude"] = beacon.latitude;
data["beacon"]["longitude"] = beacon.longitude;
data["beacon"]["overlay"] = beacon.overlay;
data["beacon"]["symbol"] = beacon.symbol;
data["beacon"]["path"] = beacon.path;
data["personalNote"] = personalNote; data["beacon"]["sendViaAPRSIS"] = beacon.sendViaAPRSIS;
data["beacon"]["sendViaRF"] = beacon.sendViaRF;
data["beacon"]["beaconFreq"] = beacon.beaconFreq;
data["blacklist"] = blacklist; data["beacon"]["statusActive"] = beacon.statusActive;
data["beacon"]["statusPacket"] = beacon.statusPacket;
data["digi"]["mode"] = digi.mode; data["beacon"]["gpsActive"] = beacon.gpsActive;
data["digi"]["ecoMode"] = digi.ecoMode; data["beacon"]["gpsAmbiguity"] = beacon.gpsAmbiguity;
#if defined(HAS_A7670)
if (digi.ecoMode == 1) data["digi"]["ecoMode"] = 2;
#endif
data["lora"]["rxFreq"] = loramodule.rxFreq; data["personalNote"] = personalNote;
data["lora"]["txFreq"] = loramodule.txFreq;
data["lora"]["spreadingFactor"] = loramodule.spreadingFactor;
data["lora"]["signalBandwidth"] = loramodule.signalBandwidth;
data["lora"]["codingRate4"] = loramodule.codingRate4;
data["lora"]["power"] = loramodule.power;
data["lora"]["txActive"] = loramodule.txActive;
data["lora"]["rxActive"] = loramodule.rxActive;
data["display"]["alwaysOn"] = display.alwaysOn; data["blacklist"] = blacklist;
data["display"]["timeout"] = display.timeout;
data["display"]["turn180"] = display.turn180;
data["battery"]["sendInternalVoltage"] = battery.sendInternalVoltage; data["digi"]["mode"] = digi.mode;
data["battery"]["monitorInternalVoltage"] = battery.monitorInternalVoltage; data["digi"]["ecoMode"] = digi.ecoMode;
data["battery"]["internalSleepVoltage"] = battery.internalSleepVoltage; #if defined(HAS_A7670)
if (digi.ecoMode == 1) data["digi"]["ecoMode"] = 2;
#endif
data["battery"]["sendExternalVoltage"] = battery.sendExternalVoltage; data["lora"]["rxActive"] = loramodule.rxActive;
data["battery"]["externalVoltagePin"] = battery.externalVoltagePin; data["lora"]["rxFreq"] = loramodule.rxFreq;
data["battery"]["monitorExternalVoltage"] = battery.monitorExternalVoltage; data["lora"]["rxSpreadingFactor"] = loramodule.rxSpreadingFactor;
data["battery"]["externalSleepVoltage"] = battery.externalSleepVoltage; data["lora"]["rxCodingRate4"] = loramodule.rxCodingRate4;
data["battery"]["voltageDividerR1"] = battery.voltageDividerR1; data["lora"]["rxSignalBandwidth"] = loramodule.rxSignalBandwidth;
data["battery"]["voltageDividerR2"] = battery.voltageDividerR2; data["lora"]["txActive"] = loramodule.txActive;
data["lora"]["txFreq"] = loramodule.txFreq;
data["lora"]["txSpreadingFactor"] = loramodule.txSpreadingFactor;
data["lora"]["txCodingRate4"] = loramodule.txCodingRate4;
data["lora"]["txSignalBandwidth"] = loramodule.txSignalBandwidth;
data["lora"]["power"] = loramodule.power;
data["battery"]["sendVoltageAsTelemetry"] = battery.sendVoltageAsTelemetry; data["display"]["alwaysOn"] = display.alwaysOn;
data["display"]["timeout"] = display.timeout;
data["display"]["turn180"] = display.turn180;
data["wxsensor"]["active"] = wxsensor.active; data["battery"]["sendInternalVoltage"] = battery.sendInternalVoltage;
data["wxsensor"]["heightCorrection"] = wxsensor.heightCorrection; data["battery"]["monitorInternalVoltage"] = battery.monitorInternalVoltage;
data["wxsensor"]["temperatureCorrection"] = wxsensor.temperatureCorrection; data["battery"]["internalSleepVoltage"] = battery.internalSleepVoltage;
data["syslog"]["active"] = syslog.active; data["battery"]["sendExternalVoltage"] = battery.sendExternalVoltage;
data["syslog"]["server"] = syslog.server; data["battery"]["externalVoltagePin"] = battery.externalVoltagePin;
data["syslog"]["port"] = syslog.port; data["battery"]["monitorExternalVoltage"] = battery.monitorExternalVoltage;
data["syslog"]["logBeaconOverTCPIP"] = syslog.logBeaconOverTCPIP; data["battery"]["externalSleepVoltage"] = battery.externalSleepVoltage;
data["battery"]["voltageDividerR1"] = battery.voltageDividerR1;
data["battery"]["voltageDividerR2"] = battery.voltageDividerR2;
data["tnc"]["enableServer"] = tnc.enableServer; data["battery"]["sendVoltageAsTelemetry"] = battery.sendVoltageAsTelemetry;
data["tnc"]["enableSerial"] = tnc.enableSerial;
data["tnc"]["acceptOwn"] = tnc.acceptOwn;
data["mqtt"]["active"] = mqtt.active; data["wxsensor"]["active"] = wxsensor.active;
data["mqtt"]["server"] = mqtt.server; data["wxsensor"]["heightCorrection"] = wxsensor.heightCorrection;
data["mqtt"]["topic"] = mqtt.topic; data["wxsensor"]["temperatureCorrection"] = wxsensor.temperatureCorrection;
data["mqtt"]["username"] = mqtt.username;
data["mqtt"]["password"] = mqtt.password;
data["mqtt"]["port"] = mqtt.port;
data["ota"]["username"] = ota.username; data["syslog"]["active"] = syslog.active;
data["ota"]["password"] = ota.password; data["syslog"]["server"] = syslog.server;
data["syslog"]["port"] = syslog.port;
data["syslog"]["logBeaconOverTCPIP"] = syslog.logBeaconOverTCPIP;
data["webadmin"]["active"] = webadmin.active; data["tnc"]["enableServer"] = tnc.enableServer;
data["webadmin"]["username"] = webadmin.username; data["tnc"]["enableSerial"] = tnc.enableSerial;
data["webadmin"]["password"] = webadmin.password; data["tnc"]["acceptOwn"] = tnc.acceptOwn;
data["tnc"]["aprsBridgeActive"] = tnc.aprsBridgeActive;
data["remoteManagement"]["managers"] = remoteManagement.managers; data["mqtt"]["active"] = mqtt.active;
data["remoteManagement"]["rfOnly"] = remoteManagement.rfOnly; data["mqtt"]["server"] = mqtt.server;
data["mqtt"]["topic"] = mqtt.topic;
data["mqtt"]["username"] = mqtt.username;
data["mqtt"]["password"] = mqtt.password;
data["mqtt"]["port"] = mqtt.port;
data["mqtt"]["beaconOverMqtt"] = mqtt.beaconOverMqtt;
data["ntp"]["gmtCorrection"] = ntp.gmtCorrection; data["ota"]["username"] = ota.username;
data["ota"]["password"] = ota.password;
data["other"]["rebootMode"] = rebootMode; data["webadmin"]["active"] = webadmin.active;
data["other"]["rebootModeTime"] = rebootModeTime; data["webadmin"]["username"] = webadmin.username;
data["webadmin"]["password"] = webadmin.password;
data["other"]["rememberStationTime"] = rememberStationTime; data["remoteManagement"]["managers"] = remoteManagement.managers;
data["remoteManagement"]["rfOnly"] = remoteManagement.rfOnly;
data["other"]["backupDigiMode"] = backupDigiMode; data["ntp"]["server"] = ntp.server;
data["ntp"]["gmtCorrection"] = ntp.gmtCorrection;
serializeJson(data, configFile); data["other"]["rebootMode"] = rebootMode;
data["other"]["rebootModeTime"] = rebootModeTime;
configFile.close(); data["other"]["rememberStationTime"] = rememberStationTime;
Serial.println("Config saved"); data["other"]["backupDigiMode"] = backupDigiMode;
delay(200);
serializeJson(data, configFile);
configFile.close();
return true;
} catch (...) {
Serial.println("Error: Exception occurred while saving config");
configFile.close();
return false;
}
} }
bool Configuration::readFile() { bool Configuration::readFile() {
Serial.println("Reading config.."); Serial.println("Reading config..");
File configFile = SPIFFS.open("/igate_conf.json", "r"); File configFile = SPIFFS.open("/igate_conf.json", "r");
if (configFile) { if (configFile) {
StaticJsonDocument<2560> data; bool needsRewrite = false;
StaticJsonDocument<3584> data;
DeserializationError error = deserializeJson(data, configFile); DeserializationError error = deserializeJson(data, configFile);
if (error) { if (error) {
@@ -173,12 +193,24 @@ bool Configuration::readFile() {
wifiAPs.push_back(wifiap); wifiAPs.push_back(wifiap);
} }
if (!data["other"].containsKey("startupDelay")) needsRewrite = true;
startupDelay = data["other"]["startupDelay"] | 0;
if (!data["wifi"]["autoAP"].containsKey("password") ||
!data["wifi"]["autoAP"].containsKey("timeout")) needsRewrite = true;
wifiAutoAP.password = data["wifi"]["autoAP"]["password"] | "1234567890"; wifiAutoAP.password = data["wifi"]["autoAP"]["password"] | "1234567890";
wifiAutoAP.timeout = data["wifi"]["autoAP"]["timeout"] | 10; wifiAutoAP.timeout = data["wifi"]["autoAP"]["timeout"] | 10;
if (!data.containsKey("callsign")) needsRewrite = true;
callsign = data["callsign"] | "NOCALL-10"; callsign = data["callsign"] | "NOCALL-10";
if (!data["aprs_is"].containsKey("active") ||
!data["aprs_is"].containsKey("passcode") ||
!data["aprs_is"].containsKey("server") ||
!data["aprs_is"].containsKey("port") ||
!data["aprs_is"].containsKey("filter") ||
!data["aprs_is"].containsKey("messagesToRF") ||
!data["aprs_is"].containsKey("objectsToRF")) needsRewrite = true;
aprs_is.active = data["aprs_is"]["active"] | false; aprs_is.active = data["aprs_is"]["active"] | false;
aprs_is.passcode = data["aprs_is"]["passcode"] | "XYZWV"; aprs_is.passcode = data["aprs_is"]["passcode"] | "XYZWV";
aprs_is.server = data["aprs_is"]["server"] | "rotate.aprs2.net"; aprs_is.server = data["aprs_is"]["server"] | "rotate.aprs2.net";
@@ -187,7 +219,20 @@ bool Configuration::readFile() {
aprs_is.messagesToRF = data["aprs_is"]["messagesToRF"] | false; aprs_is.messagesToRF = data["aprs_is"]["messagesToRF"] | false;
aprs_is.objectsToRF = data["aprs_is"]["objectsToRF"] | false; aprs_is.objectsToRF = data["aprs_is"]["objectsToRF"] | false;
if (!data["beacon"].containsKey("latitude") ||
!data["beacon"].containsKey("longitude") ||
!data["beacon"].containsKey("comment") ||
!data["beacon"].containsKey("interval") ||
!data["beacon"].containsKey("overlay") ||
!data["beacon"].containsKey("symbol") ||
!data["beacon"].containsKey("path") ||
!data["beacon"].containsKey("sendViaAPRSIS") ||
!data["beacon"].containsKey("sendViaRF") ||
!data["beacon"].containsKey("beaconFreq") ||
!data["beacon"].containsKey("statusActive") ||
!data["beacon"].containsKey("statusPacket") ||
!data["beacon"].containsKey("gpsActive") ||
!data["beacon"].containsKey("gpsAmbiguity")) 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";
@@ -197,88 +242,149 @@ 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.gpsAmbiguity = data["beacon"]["gpsAmbiguity"] | false;
if (!data.containsKey("personalNote")) needsRewrite = true;
personalNote = data["personalNote"] | "personal note here"; personalNote = data["personalNote"] | "personal note here";
if (!data.containsKey("blacklist")) needsRewrite = true;
blacklist = data["blacklist"] | "station callsign"; blacklist = data["blacklist"] | "station callsign";
if (!data["digi"].containsKey("mode") ||
!data["digi"].containsKey("ecoMode")) 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
loramodule.txFreq = data["lora"]["txFreq"] | 433775000; if (!data["lora"].containsKey("rxActive") ||
!data["lora"].containsKey("rxFreq") ||
!data["lora"].containsKey("rxSpreadingFactor") ||
!data["lora"].containsKey("rxCodingRate4") ||
!data["lora"].containsKey("rxSignalBandwidth") ||
!data["lora"].containsKey("txActive") ||
!data["lora"].containsKey("txFreq") ||
!data["lora"].containsKey("txSpreadingFactor") ||
!data["lora"].containsKey("txCodingRate4") ||
!data["lora"].containsKey("txSignalBandwidth") ||
!data["lora"].containsKey("power")) needsRewrite = true;
loramodule.rxActive = data["lora"]["rxActive"] | true;
loramodule.rxFreq = data["lora"]["rxFreq"] | 433775000; loramodule.rxFreq = data["lora"]["rxFreq"] | 433775000;
loramodule.spreadingFactor = data["lora"]["spreadingFactor"] | 12; loramodule.rxSpreadingFactor = data["lora"]["rxSpreadingFactor"] | 12;
loramodule.signalBandwidth = data["lora"]["signalBandwidth"] | 125000; loramodule.rxCodingRate4 = data["lora"]["rxCodingRate4"] | 5;
loramodule.codingRate4 = data["lora"]["codingRate4"] | 5; loramodule.rxSignalBandwidth = data["lora"]["rxSignalBandwidth"] | 125000;
loramodule.power = data["lora"]["power"] | 20;
loramodule.txActive = data["lora"]["txActive"] | false; loramodule.txActive = data["lora"]["txActive"] | false;
loramodule.rxActive = data["lora"]["rxActive"] | false; loramodule.txFreq = data["lora"]["txFreq"] | 433775000;
loramodule.txSpreadingFactor = data["lora"]["txSpreadingFactor"] | 12;
loramodule.txCodingRate4 = data["lora"]["txCodingRate4"] | 5;
loramodule.txSignalBandwidth = data["lora"]["txSignalBandwidth"] | 125000;
loramodule.power = data["lora"]["power"] | 20;
if (!data["display"].containsKey("alwaysOn") ||
!data["display"].containsKey("timeout") ||
!data["display"].containsKey("turn180")) needsRewrite = true;
display.alwaysOn = data["display"]["alwaysOn"] | true; display.alwaysOn = data["display"]["alwaysOn"] | true;
display.timeout = data["display"]["timeout"] | 4; display.timeout = data["display"]["timeout"] | 4;
display.turn180 = data["display"]["turn180"] | false; display.turn180 = data["display"]["turn180"] | false;
if (!data["battery"].containsKey("sendInternalVoltage") ||
!data["battery"].containsKey("monitorInternalVoltage") ||
!data["battery"].containsKey("internalSleepVoltage") ||
!data["battery"].containsKey("sendExternalVoltage") ||
!data["battery"].containsKey("externalVoltagePin") ||
!data["battery"].containsKey("monitorExternalVoltage") ||
!data["battery"].containsKey("externalSleepVoltage") ||
!data["battery"].containsKey("voltageDividerR1") ||
!data["battery"].containsKey("voltageDividerR2") ||
!data["battery"].containsKey("sendVoltageAsTelemetry")) needsRewrite = true;
battery.sendInternalVoltage = data["battery"]["sendInternalVoltage"] | false; battery.sendInternalVoltage = data["battery"]["sendInternalVoltage"] | false;
battery.monitorInternalVoltage = data["battery"]["monitorInternalVoltage"] | false; battery.monitorInternalVoltage = data["battery"]["monitorInternalVoltage"] | false;
battery.internalSleepVoltage = data["battery"]["internalSleepVoltage"] | 2.9; battery.internalSleepVoltage = data["battery"]["internalSleepVoltage"] | 2.9;
battery.sendExternalVoltage = data["battery"]["sendExternalVoltage"] | false; battery.sendExternalVoltage = data["battery"]["sendExternalVoltage"] | false;
battery.externalVoltagePin = data["battery"]["externalVoltagePin"] | 34; battery.externalVoltagePin = data["battery"]["externalVoltagePin"] | 34;
battery.monitorExternalVoltage = data["battery"]["monitorExternalVoltage"] | false; battery.monitorExternalVoltage = data["battery"]["monitorExternalVoltage"] | false;
battery.externalSleepVoltage = data["battery"]["externalSleepVoltage"] | 10.9; battery.externalSleepVoltage = data["battery"]["externalSleepVoltage"] | 10.9;
battery.voltageDividerR1 = data["battery"]["voltageDividerR1"] | 100.0; battery.voltageDividerR1 = data["battery"]["voltageDividerR1"] | 100.0;
battery.voltageDividerR2 = data["battery"]["voltageDividerR2"] | 27.0; battery.voltageDividerR2 = data["battery"]["voltageDividerR2"] | 27.0;
battery.sendVoltageAsTelemetry = data["battery"]["sendVoltageAsTelemetry"] | false; battery.sendVoltageAsTelemetry = data["battery"]["sendVoltageAsTelemetry"] | false;
if (!data["wxsensor"].containsKey("active") ||
!data["wxsensor"].containsKey("heightCorrection") ||
!data["wxsensor"].containsKey("temperatureCorrection")) needsRewrite = true;
wxsensor.active = data["wxsensor"]["active"] | false; wxsensor.active = data["wxsensor"]["active"] | false;
wxsensor.heightCorrection = data["wxsensor"]["heightCorrection"] | 0; wxsensor.heightCorrection = data["wxsensor"]["heightCorrection"] | 0;
wxsensor.temperatureCorrection = data["wxsensor"]["temperatureCorrection"] | 0.0; wxsensor.temperatureCorrection = data["wxsensor"]["temperatureCorrection"] | 0.0;
if (!data["syslog"].containsKey("active") ||
!data["syslog"].containsKey("server") ||
!data["syslog"].containsKey("port") ||
!data["syslog"].containsKey("logBeaconOverTCPIP")) needsRewrite = true;
syslog.active = data["syslog"]["active"] | false; syslog.active = data["syslog"]["active"] | false;
syslog.server = data["syslog"]["server"] | "lora.link9.net"; syslog.server = data["syslog"]["server"] | "lora.link9.net";
syslog.port = data["syslog"]["port"] | 1514; syslog.port = data["syslog"]["port"] | 1514;
syslog.logBeaconOverTCPIP = data["syslog"]["logBeaconOverTCPIP"] | false; syslog.logBeaconOverTCPIP = data["syslog"]["logBeaconOverTCPIP"] | false;
if (!data["tnc"].containsKey("enableServer") ||
!data["tnc"].containsKey("enableSerial") ||
!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") ||
!data["mqtt"].containsKey("server") ||
!data["mqtt"].containsKey("topic") ||
!data["mqtt"].containsKey("username") ||
!data["mqtt"].containsKey("password") ||
!data["mqtt"].containsKey("port") ||
!data["mqtt"].containsKey("beaconOverMqtt")) needsRewrite = true;
mqtt.active = data["mqtt"]["active"] | false; mqtt.active = data["mqtt"]["active"] | false;
mqtt.server = data["mqtt"]["server"] | ""; mqtt.server = data["mqtt"]["server"] | "";
mqtt.topic = data["mqtt"]["topic"] | "aprs-igate"; mqtt.topic = data["mqtt"]["topic"] | "aprs-igate";
mqtt.username = data["mqtt"]["username"] | ""; mqtt.username = data["mqtt"]["username"] | "";
mqtt.password = data["mqtt"]["password"] | ""; mqtt.password = data["mqtt"]["password"] | "";
mqtt.port = data["mqtt"]["port"] | 1883; mqtt.port = data["mqtt"]["port"] | 1883;
mqtt.beaconOverMqtt = data["mqtt"]["beaconOverMqtt"] | false;
if (!data["ota"].containsKey("username") ||
!data["ota"].containsKey("password")) needsRewrite = true;
ota.username = data["ota"]["username"] | ""; ota.username = data["ota"]["username"] | "";
ota.password = data["ota"]["password"] | ""; ota.password = data["ota"]["password"] | "";
if (!data["webadmin"].containsKey("active") ||
!data["webadmin"].containsKey("username") ||
!data["webadmin"].containsKey("password")) needsRewrite = true;
webadmin.active = data["webadmin"]["active"] | false; webadmin.active = data["webadmin"]["active"] | false;
webadmin.username = data["webadmin"]["username"] | "admin"; webadmin.username = data["webadmin"]["username"] | "admin";
webadmin.password = data["webadmin"]["password"] | ""; webadmin.password = data["webadmin"]["password"] | "";
if (!data["remoteManagement"].containsKey("managers") ||
!data["remoteManagement"].containsKey("rfOnly")) needsRewrite = true;
remoteManagement.managers = data["remoteManagement"]["managers"] | ""; remoteManagement.managers = data["remoteManagement"]["managers"] | "";
remoteManagement.rfOnly = data["remoteManagement"]["rfOnly"] | true; remoteManagement.rfOnly = data["remoteManagement"]["rfOnly"] | true;
if (!data["ntp"].containsKey("server") ||
!data["ntp"].containsKey("gmtCorrection")) needsRewrite = true;
ntp.server = data["ntp"]["server"] | "pool.ntp.org";
ntp.gmtCorrection = data["ntp"]["gmtCorrection"] | 0.0; ntp.gmtCorrection = data["ntp"]["gmtCorrection"] | 0.0;
if (!data["other"].containsKey("rebootMode") ||
!data["other"].containsKey("rebootModeTime")) needsRewrite = true;
rebootMode = data["other"]["rebootMode"] | false; rebootMode = data["other"]["rebootMode"] | false;
rebootModeTime = data["other"]["rebootModeTime"] | 6; rebootModeTime = data["other"]["rebootModeTime"] | 6;
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; 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
@@ -289,6 +395,13 @@ bool Configuration::readFile() {
wifiAPs.push_back(wifiap); wifiAPs.push_back(wifiap);
} }
configFile.close(); configFile.close();
if (needsRewrite) {
Serial.println("Config JSON incomplete, rewriting...");
writeFile();
delay(1000);
ESP.restart();
}
Serial.println("Config read successfuly"); Serial.println("Config read successfuly");
return true; return true;
} else { } else {
@@ -297,7 +410,7 @@ bool Configuration::readFile() {
} }
} }
void Configuration::init() { void Configuration::setDefaultValues() {
WiFi_AP wifiap; WiFi_AP wifiap;
wifiap.ssid = ""; wifiap.ssid = "";
@@ -305,6 +418,8 @@ void Configuration::init() {
wifiAPs.push_back(wifiap); wifiAPs.push_back(wifiap);
startupDelay = 0;
wifiAutoAP.password = "1234567890"; wifiAutoAP.password = "1234567890";
wifiAutoAP.timeout = 10; wifiAutoAP.timeout = 10;
@@ -324,10 +439,12 @@ void Configuration::init() {
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 = "";
@@ -341,14 +458,17 @@ void Configuration::init() {
digi.mode = 0; digi.mode = 0;
digi.ecoMode = 0; digi.ecoMode = 0;
loramodule.txFreq = 433775000;
loramodule.rxFreq = 433775000;
loramodule.spreadingFactor = 12;
loramodule.signalBandwidth = 125000;
loramodule.codingRate4 = 5;
loramodule.power = 20;
loramodule.txActive = false;
loramodule.rxActive = true; loramodule.rxActive = true;
loramodule.rxFreq = 433775000;
loramodule.rxSpreadingFactor = 12;
loramodule.rxCodingRate4 = 5;
loramodule.rxSignalBandwidth = 125000;
loramodule.txActive = false;
loramodule.txFreq = 433775000;
loramodule.txSpreadingFactor = 12;
loramodule.txCodingRate4 = 5;
loramodule.txSignalBandwidth = 125000;
loramodule.power = 20;
display.alwaysOn = true; display.alwaysOn = true;
display.timeout = 4; display.timeout = 4;
@@ -379,6 +499,7 @@ void Configuration::init() {
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 = "";
@@ -386,6 +507,7 @@ void Configuration::init() {
mqtt.username = ""; mqtt.username = "";
mqtt.password = ""; mqtt.password = "";
mqtt.port = 1883; mqtt.port = 1883;
mqtt.beaconOverMqtt = false;
ota.username = ""; ota.username = "";
ota.password = ""; ota.password = "";
@@ -397,6 +519,7 @@ void Configuration::init() {
remoteManagement.managers = ""; remoteManagement.managers = "";
remoteManagement.rfOnly = true; remoteManagement.rfOnly = true;
ntp.server = "pool.ntp.org";
ntp.gmtCorrection = 0.0; ntp.gmtCorrection = 0.0;
rebootMode = false; rebootMode = false;
@@ -419,8 +542,9 @@ Configuration::Configuration() {
bool exists = SPIFFS.exists("/igate_conf.json"); bool exists = SPIFFS.exists("/igate_conf.json");
if (!exists) { if (!exists) {
init(); setDefaultValues();
writeFile(); writeFile();
delay(1000);
ESP.restart(); ESP.restart();
} }
+1
View File
@@ -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
+19 -8
View File
@@ -30,6 +30,7 @@
extern Configuration Config; extern Configuration Config;
extern uint32_t lastRxTime; extern uint32_t lastRxTime;
extern bool packetIsBeacon;
extern std::vector<ReceivedPacket> receivedPackets; extern std::vector<ReceivedPacket> receivedPackets;
@@ -92,10 +93,10 @@ namespace LoRa_Utils {
#if defined(HAS_SX1278) || defined(HAS_SX1276) #if defined(HAS_SX1278) || defined(HAS_SX1276)
radio.setDio0Action(setFlag, RISING); radio.setDio0Action(setFlag, RISING);
#endif #endif
radio.setSpreadingFactor(Config.loramodule.spreadingFactor); radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor);
float signalBandwidth = Config.loramodule.signalBandwidth/1000; radio.setCodingRate(Config.loramodule.rxCodingRate4);
radio.setBandwidth(signalBandwidth); float signalBandwidth = Config.loramodule.rxSignalBandwidth/1000;
radio.setCodingRate(Config.loramodule.codingRate4); radio.setBandwidth(signalBandwidth);
radio.setCRC(true); radio.setCRC(true);
#if (defined(RADIO_RXEN) && defined(RADIO_TXEN)) // QRP Labs LightGateway has 400M22S (SX1268) #if (defined(RADIO_RXEN) && defined(RADIO_TXEN)) // QRP Labs LightGateway has 400M22S (SX1268)
@@ -128,22 +129,30 @@ 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.setCodingRate(Config.loramodule.txCodingRate4);
radio.setBandwidth(Config.loramodule.txSignalBandwidth);
} }
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.setCodingRate(Config.loramodule.rxCodingRate4);
radio.setBandwidth(Config.loramodule.rxSignalBandwidth);
} }
void sendNewPacket(const String& newPacket) { void sendNewPacket(const String& newPacket) {
if (!Config.loramodule.txActive) return; if (!Config.loramodule.txActive) return;
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) { if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
changeFreqTx(); if (!packetIsBeacon || (packetIsBeacon && Config.beacon.beaconFreq == 1)) {
changeFreqTx();
}
} }
#ifdef INTERNAL_LED_PIN #ifdef INTERNAL_LED_PIN
@@ -165,7 +174,9 @@ 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) {
changeFreqRx(); if (!packetIsBeacon || (packetIsBeacon && Config.beacon.beaconFreq == 1)) {
changeFreqRx();
}
} }
} }
+5 -5
View File
@@ -27,7 +27,7 @@
extern Configuration Config; extern Configuration Config;
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 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";
} }
+31 -8
View File
@@ -33,13 +33,26 @@ extern bool shouldSleepLowVoltage;
uint32_t lastTxTime = millis(); uint32_t lastTxTime = millis();
std::vector<LastHeardStation> lastHeardStations; std::vector<LastHeardStation> lastHeardStations;
std::vector<String> outputPacketBuffer;
std::vector<Packet25SegBuffer> packet25SegBuffer;
std::vector<String> blacklist; std::vector<String> blacklist;
std::vector<String> managers; std::vector<String> managers;
std::vector<LastHeardStation> lastHeardObjects; std::vector<LastHeardStation> lastHeardObjects;
struct OutputPacketBuffer {
String packet;
bool isBeacon;
};
std::vector<OutputPacketBuffer> outputPacketBuffer;
struct Packet25SegBuffer {
uint32_t receivedTime;
String station;
String payload;
};
std::vector<Packet25SegBuffer> packet25SegBuffer;
bool saveNewDigiEcoModeConfig = false; bool saveNewDigiEcoModeConfig = false;
bool packetIsBeacon = false;
namespace STATION_Utils { namespace STATION_Utils {
@@ -138,7 +151,7 @@ namespace STATION_Utils {
} }
} }
if (!stationHeard) lastHeardStations.emplace_back(LastHeardStation{millis(), station}); if (!stationHeard) lastHeardStations.emplace_back(LastHeardStation{millis(), station});
Utils::activeStations(); Utils::showActiveStations();
} }
bool wasHeard(const String& station) { bool wasHeard(const String& station) {
@@ -171,7 +184,9 @@ namespace STATION_Utils {
size_t currentIndex = 0; size_t currentIndex = 0;
while (currentIndex < outputPacketBuffer.size()) { // this sends all packets from output buffer while (currentIndex < outputPacketBuffer.size()) { // this sends all packets from output buffer
delay(3000); // and cleans buffer to avoid sending packets with time offset delay(3000); // and cleans buffer to avoid sending packets with time offset
LoRa_Utils::sendNewPacket(outputPacketBuffer[currentIndex]); // next time it wakes up if (outputPacketBuffer[currentIndex].isBeacon) packetIsBeacon = true;
LoRa_Utils::sendNewPacket(outputPacketBuffer[currentIndex].packet); // next time it wakes up
if (outputPacketBuffer[currentIndex].isBeacon) packetIsBeacon = false;
currentIndex++; currentIndex++;
} }
outputPacketBuffer.clear(); outputPacketBuffer.clear();
@@ -190,13 +205,17 @@ namespace STATION_Utils {
uint32_t lastRx = millis() - lastRxTime; uint32_t lastRx = millis() - lastRxTime;
uint32_t lastTx = millis() - lastTxTime; uint32_t lastTx = millis() - lastTxTime;
if (outputPacketBuffer.size() > 0 && lastTx > timeToWait && lastRx > timeToWait) { if (outputPacketBuffer.size() > 0 && lastTx > timeToWait && lastRx > timeToWait) {
LoRa_Utils::sendNewPacket(outputPacketBuffer[0]); if (outputPacketBuffer[0].isBeacon) packetIsBeacon = true;
LoRa_Utils::sendNewPacket(outputPacketBuffer[0].packet);
if (outputPacketBuffer[0].isBeacon) packetIsBeacon = false;
outputPacketBuffer.erase(outputPacketBuffer.begin()); outputPacketBuffer.erase(outputPacketBuffer.begin());
lastTxTime = millis(); lastTxTime = millis();
} }
if (shouldSleepLowVoltage) { if (shouldSleepLowVoltage) {
while (outputPacketBuffer.size() > 0) { while (outputPacketBuffer.size() > 0) {
LoRa_Utils::sendNewPacket(outputPacketBuffer[0]); if (outputPacketBuffer[0].isBeacon) packetIsBeacon = true;
LoRa_Utils::sendNewPacket(outputPacketBuffer[0].packet);
if (outputPacketBuffer[0].isBeacon) packetIsBeacon = false;
outputPacketBuffer.erase(outputPacketBuffer.begin()); outputPacketBuffer.erase(outputPacketBuffer.begin());
delay(4000); delay(4000);
} }
@@ -209,8 +228,12 @@ namespace STATION_Utils {
} }
} }
void addToOutputPacketBuffer(const String& packet) { void addToOutputPacketBuffer(const String& packet, bool flag) {
outputPacketBuffer.push_back(packet); OutputPacketBuffer entry;
entry.packet = packet;
entry.isBeacon = flag;
outputPacketBuffer.push_back(entry);
} }
} }
+10 -6
View File
@@ -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();
} }
+12 -4
View File
@@ -88,7 +88,7 @@ namespace Utils {
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); STATION_Utils::addToOutputPacketBuffer(status, true); // treated also as beacon on Tx Freq
statusAfterBoot = false; statusAfterBoot = false;
} }
} }
@@ -127,7 +127,7 @@ namespace Utils {
seventhLine = " listening..."; seventhLine = " listening...";
} }
void activeStations() { void showActiveStations() {
char buffer[30]; // Adjust size as needed char buffer[30]; // Adjust size as needed
sprintf(buffer, "Stations (%dmin) = %2d", Config.rememberStationTime, lastHeardStations.size()); sprintf(buffer, "Stations (%dmin) = %2d", Config.rememberStationTime, lastHeardStations.size());
fourthLine = buffer; fourthLine = buffer;
@@ -159,7 +159,7 @@ namespace Utils {
STATION_Utils::deleteNotHeard(); STATION_Utils::deleteNotHeard();
activeStations(); showActiveStations();
beaconPacket = iGateBeaconPacket; beaconPacket = iGateBeaconPacket;
secondaryBeaconPacket = iGateLoRaBeaconPacket; secondaryBeaconPacket = iGateLoRaBeaconPacket;
@@ -259,7 +259,7 @@ namespace Utils {
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...";
STATION_Utils::addToOutputPacketBuffer(secondaryBeaconPacket); STATION_Utils::addToOutputPacketBuffer(secondaryBeaconPacket, true);
} }
lastBeaconTx = millis(); lastBeaconTx = millis();
@@ -284,6 +284,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();
} }
@@ -436,4 +437,11 @@ namespace Utils {
return true; return true;
} }
void startupDelay() {
if (Config.startupDelay > 0) {
displayShow("", " STARTUP DELAY ...", "", "", 0);
delay(Config.startupDelay * 60 * 1000);
}
}
} }
+125 -75
View File
@@ -115,159 +115,209 @@ namespace WEB_Utils {
} }
void handleWriteConfiguration(AsyncWebServerRequest *request) { void handleWriteConfiguration(AsyncWebServerRequest *request) {
Serial.println("Got new config from www"); Serial.println("Got new Configuration Data from www");
int networks = request->getParam("wifi.APs", true)->value().toInt(); auto getParamStringSafe = [&](const String& name, const String& defaultValue = "") -> String {
if (request->hasParam(name, true)) {
return request->getParam(name, true)->value();
}
return defaultValue;
};
auto getParamIntSafe = [&](const String& name, int defaultValue = 0) -> int {
if (request->hasParam(name, true)) {
return request->getParam(name, true)->value().toInt();
}
return defaultValue;
};
auto getParamFloatSafe = [&](const String& name, float defaultValue = 0.0) -> float {
if (request->hasParam(name, true)) {
return request->getParam(name, true)->value().toFloat();
}
return defaultValue;
};
auto getParamDoubleSafe = [&](const String& name, double defaultValue = 0.0) -> double {
if (request->hasParam(name, true)) {
return request->getParam(name, true)->value().toDouble();
}
return defaultValue;
};
int networks = getParamIntSafe("wifi.APs");
Config.wifiAPs = {}; Config.wifiAPs = {};
for (int i=0; i<networks; i++) { for (int i = 0; i < networks; i++) {
WiFi_AP wifiap; WiFi_AP wifiap;
wifiap.ssid = request->getParam("wifi.AP." + String(i) + ".ssid", true)->value(); wifiap.ssid = getParamStringSafe("wifi.AP." + String(i) + ".ssid");
wifiap.password = request->getParam("wifi.AP." + String(i) + ".password", true)->value(); wifiap.password = getParamStringSafe("wifi.AP." + String(i) + ".password");
Config.wifiAPs.push_back(wifiap); Config.wifiAPs.push_back(wifiap);
} }
Config.callsign = request->getParam("callsign", true)->value(); Config.startupDelay = getParamIntSafe("startupDelay", Config.startupDelay);
Config.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value();
Config.wifiAutoAP.timeout = request->getParam("wifi.autoAP.timeout", true)->value().toInt();
Config.callsign = getParamStringSafe("callsign", Config.callsign);
Config.wifiAutoAP.password = getParamStringSafe("wifi.autoAP.password", Config.wifiAutoAP.password);
Config.wifiAutoAP.timeout = getParamIntSafe("wifi.autoAP.timeout", Config.wifiAutoAP.timeout);
Config.aprs_is.active = request->hasParam("aprs_is.active", true); Config.aprs_is.active = request->hasParam("aprs_is.active", true);
if (Config.aprs_is.active) { if (Config.aprs_is.active) {
Config.aprs_is.messagesToRF = request->hasParam("aprs_is.messagesToRF", true); Config.aprs_is.messagesToRF = request->hasParam("aprs_is.messagesToRF", true);
Config.aprs_is.objectsToRF = request->hasParam("aprs_is.objectsToRF", true); Config.aprs_is.objectsToRF = request->hasParam("aprs_is.objectsToRF", true);
Config.aprs_is.server = request->getParam("aprs_is.server", true)->value(); Config.aprs_is.server = getParamStringSafe("aprs_is.server", Config.aprs_is.server);
Config.aprs_is.passcode = request->getParam("aprs_is.passcode", true)->value(); Config.aprs_is.passcode = getParamStringSafe("aprs_is.passcode", Config.aprs_is.passcode);
Config.aprs_is.port = request->getParam("aprs_is.port", true)->value().toInt(); Config.aprs_is.port = getParamIntSafe("aprs_is.port", Config.aprs_is.port);
Config.aprs_is.filter = request->getParam("aprs_is.filter", true)->value(); Config.aprs_is.filter = getParamStringSafe("aprs_is.filter", Config.aprs_is.filter);
} }
Config.beacon.interval = request->getParam("beacon.interval", true)->value().toInt(); 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.latitude = request->getParam("beacon.latitude", true)->value().toDouble(); Config.beacon.beaconFreq = getParamIntSafe("beacon.beaconFreq", Config.beacon.beaconFreq);
Config.beacon.longitude = request->getParam("beacon.longitude", true)->value().toDouble(); Config.beacon.latitude = getParamDoubleSafe("beacon.latitude", Config.beacon.latitude);
Config.beacon.comment = request->getParam("beacon.comment", true)->value(); Config.beacon.longitude = getParamDoubleSafe("beacon.longitude", Config.beacon.longitude);
Config.beacon.overlay = request->getParam("beacon.overlay", true)->value(); Config.beacon.comment = getParamStringSafe("beacon.comment", Config.beacon.comment);
Config.beacon.symbol = request->getParam("beacon.symbol", true)->value(); Config.beacon.overlay = getParamStringSafe("beacon.overlay", Config.beacon.overlay);
Config.beacon.path = request->getParam("beacon.path", true)->value(); Config.beacon.symbol = getParamStringSafe("beacon.symbol", Config.beacon.symbol);
Config.beacon.path = getParamStringSafe("beacon.path", Config.beacon.path);
Config.beacon.statusActive = request->hasParam("beacon.statusActive", true); Config.beacon.statusActive = request->hasParam("beacon.statusActive", true);
if (Config.beacon.statusActive) { if (Config.beacon.statusActive) {
Config.beacon.statusPacket = request->getParam("beacon.statusPacket", true)->value(); Config.beacon.statusPacket = getParamStringSafe("beacon.statusPacket", Config.beacon.statusPacket);
} }
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.gpsAmbiguity = request->hasParam("beacon.gpsAmbiguity", true);
Config.personalNote = request->getParam("personalNote", true)->value(); Config.personalNote = getParamStringSafe("personalNote", Config.personalNote);
Config.blacklist = request->getParam("blacklist", true)->value(); Config.blacklist = getParamStringSafe("blacklist", Config.blacklist);
Config.digi.mode = request->getParam("digi.mode", true)->value().toInt(); Config.digi.mode = getParamIntSafe("digi.mode", Config.digi.mode);
Config.digi.ecoMode = request->getParam("digi.ecoMode", true)->value().toInt();; Config.digi.ecoMode = getParamIntSafe("digi.ecoMode", Config.digi.ecoMode);
Config.loramodule.txFreq = request->getParam("lora.txFreq", true)->value().toInt();
Config.loramodule.rxFreq = request->getParam("lora.rxFreq", true)->value().toInt();
Config.loramodule.spreadingFactor = request->getParam("lora.spreadingFactor", true)->value().toInt();
Config.loramodule.signalBandwidth = request->getParam("lora.signalBandwidth", true)->value().toInt();
Config.loramodule.codingRate4 = request->getParam("lora.codingRate4", true)->value().toInt();
Config.loramodule.power = request->getParam("lora.power", true)->value().toInt();
Config.loramodule.txActive = request->hasParam("lora.txActive", 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.rxSpreadingFactor = getParamIntSafe("lora.rxSpreadingFactor", Config.loramodule.rxSpreadingFactor);
Config.loramodule.rxCodingRate4 = getParamIntSafe("lora.rxCodingRate4", Config.loramodule.rxCodingRate4);
Config.loramodule.rxSignalBandwidth = getParamIntSafe("lora.rxSignalBandwidth", Config.loramodule.rxSignalBandwidth);
Config.loramodule.txActive = request->hasParam("lora.txActive", true);
Config.loramodule.txFreq = getParamIntSafe("lora.txFreq", Config.loramodule.txFreq);
Config.loramodule.txSpreadingFactor = getParamIntSafe("lora.txSpreadingFactor", Config.loramodule.txSpreadingFactor);
Config.loramodule.txCodingRate4 = getParamIntSafe("lora.txCodingRate4", Config.loramodule.txCodingRate4);
Config.loramodule.txSignalBandwidth = getParamIntSafe("lora.txSignalBandwidth", Config.loramodule.txSignalBandwidth);
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 = request->getParam("display.timeout", true)->value().toInt(); 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) {
Config.battery.internalSleepVoltage = request->getParam("battery.internalSleepVoltage", true)->value().toFloat(); Config.battery.internalSleepVoltage = getParamFloatSafe("battery.internalSleepVoltage", Config.battery.internalSleepVoltage);
} }
Config.battery.sendExternalVoltage = request->hasParam("battery.sendExternalVoltage", true); Config.battery.sendExternalVoltage = request->hasParam("battery.sendExternalVoltage", true);
if (Config.battery.sendExternalVoltage) { if (Config.battery.sendExternalVoltage) {
Config.battery.externalVoltagePin = request->getParam("battery.externalVoltagePin", true)->value().toInt(); Config.battery.externalVoltagePin = getParamIntSafe("battery.externalVoltagePin", Config.battery.externalVoltagePin);
Config.battery.voltageDividerR1 = request->getParam("battery.voltageDividerR1", true)->value().toFloat(); Config.battery.voltageDividerR1 = getParamFloatSafe("battery.voltageDividerR1", Config.battery.voltageDividerR1);
Config.battery.voltageDividerR2 = request->getParam("battery.voltageDividerR2", true)->value().toFloat(); Config.battery.voltageDividerR2 = getParamFloatSafe("battery.voltageDividerR2", Config.battery.voltageDividerR2);
} }
Config.battery.monitorExternalVoltage = request->hasParam("battery.monitorExternalVoltage", true); Config.battery.monitorExternalVoltage = request->hasParam("battery.monitorExternalVoltage", true);
if (Config.battery.monitorExternalVoltage) { if (Config.battery.monitorExternalVoltage) {
Config.battery.externalSleepVoltage = request->getParam("battery.externalSleepVoltage", true)->value().toFloat(); Config.battery.externalSleepVoltage = getParamFloatSafe("battery.externalSleepVoltage", Config.battery.externalSleepVoltage);
} }
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 = request->getParam("wxsensor.heightCorrection", true)->value().toInt(); Config.wxsensor.heightCorrection = getParamIntSafe("wxsensor.heightCorrection", Config.wxsensor.heightCorrection);
Config.wxsensor.temperatureCorrection = request->getParam("wxsensor.temperatureCorrection", true)->value().toFloat(); Config.wxsensor.temperatureCorrection = getParamFloatSafe("wxsensor.temperatureCorrection", Config.wxsensor.temperatureCorrection);
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 = request->getParam("syslog.server", true)->value(); Config.syslog.server = getParamStringSafe("syslog.server", Config.syslog.server);
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt(); Config.syslog.port = getParamIntSafe("syslog.port", Config.syslog.port);
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.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 = request->getParam("mqtt.server", true)->value(); Config.mqtt.server = getParamStringSafe("mqtt.server", Config.mqtt.server);
Config.mqtt.topic = request->getParam("mqtt.topic", true)->value(); Config.mqtt.topic = getParamStringSafe("mqtt.topic", Config.mqtt.topic);
Config.mqtt.username = request->getParam("mqtt.username", true)->value(); Config.mqtt.username = getParamStringSafe("mqtt.username", Config.mqtt.username);
Config.mqtt.password = request->getParam("mqtt.password", true)->value(); Config.mqtt.password = getParamStringSafe("mqtt.password", Config.mqtt.password);
Config.mqtt.port = request->getParam("mqtt.port", true)->value().toInt(); Config.mqtt.port = getParamIntSafe("mqtt.port", Config.mqtt.port);
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 = request->getParam("other.rebootModeTime", true)->value().toInt(); Config.rebootModeTime = getParamIntSafe("other.rebootModeTime", Config.rebootModeTime);
} }
Config.ota.username = request->getParam("ota.username", true)->value(); Config.ota.username = getParamStringSafe("ota.username", Config.ota.username);
Config.ota.password = request->getParam("ota.password", true)->value(); Config.ota.password = getParamStringSafe("ota.password", Config.ota.password);
Config.webadmin.active = request->hasParam("webadmin.active", true); Config.webadmin.active = request->hasParam("webadmin.active", true);
if (Config.webadmin.active) { if (Config.webadmin.active) {
Config.webadmin.username = request->getParam("webadmin.username", true)->value(); Config.webadmin.username = getParamStringSafe("webadmin.username", Config.webadmin.username);
Config.webadmin.password = request->getParam("webadmin.password", true)->value(); Config.webadmin.password = getParamStringSafe("webadmin.password", Config.webadmin.password);
} }
Config.remoteManagement.managers = request->getParam("remoteManagement.managers", true)->value(); Config.remoteManagement.managers = getParamStringSafe("remoteManagement.managers", Config.remoteManagement.managers);
Config.remoteManagement.rfOnly = request->hasParam("remoteManagement.rfOnly", true); Config.remoteManagement.rfOnly = request->hasParam("remoteManagement.rfOnly", true);
Config.ntp.gmtCorrection = request->getParam("ntp.gmtCorrection", true)->value().toFloat(); Config.ntp.server = getParamStringSafe("ntp.server", Config.ntp.server);
Config.ntp.gmtCorrection = getParamFloatSafe("ntp.gmtCorrection", Config.ntp.gmtCorrection);
Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt(); Config.rememberStationTime = getParamIntSafe("other.rememberStationTime", Config.rememberStationTime);
Config.backupDigiMode = request->hasParam("other.backupDigiMode", true); Config.backupDigiMode = request->hasParam("other.backupDigiMode", true);
bool saveSuccess = Config.writeFile();
Config.writeFile(); if (saveSuccess) {
Serial.println("Configuration saved successfully");
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", ""); AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
response->addHeader("Location", "/"); response->addHeader("Location", "/?success=1");
request->send(response); request->send(response);
displayToggle(false);
delay(200); displayToggle(false);
ESP.restart(); delay(500);
ESP.restart();
} else {
Serial.println("Error saving configuration!");
String errorPage = "<!DOCTYPE html><html><head><title>Error</title></head><body>";
errorPage += "<h1>Configuration Error:</h1>";
errorPage += "<p>Couldn't save new configuration. Please try again.</p>";
errorPage += "<a href='/'>Back</a></body></html>";
AsyncWebServerResponse *response = request->beginResponse(500, "text/html", errorPage);
request->send(response);
}
} }
void handleAction(AsyncWebServerRequest *request) { void handleAction(AsyncWebServerRequest *request) {
+50
View File
@@ -0,0 +1,50 @@
/* 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_SX1278
#define RADIO_SCLK_PIN 36
#define RADIO_MISO_PIN 37
#define RADIO_MOSI_PIN 35
#define RADIO_CS_PIN 34
#define RADIO_RST_PIN 2
#define RADIO_BUSY_PIN 3
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_3
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display
//#define HAS_DISPLAY
#undef OLED_SDA
#undef OLED_SCL
#undef OLED_RST
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin)
// Aditional Config
#define INTERNAL_LED_PIN 39
#endif
+8
View File
@@ -0,0 +1,8 @@
[env:LoRaHAM_V2]
board = esp32dev
build_flags =
${common.build_flags}
-D LoRaHAM_V2
lib_deps =
${common.lib_deps}
${common.display_libs}
@@ -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 21
#define OLED_SCL 22
#define OLED_RST -1
// Aditional Config
#define INTERNAL_LED_PIN 16
/*
Green LED (Lora): PIN 22 / GPIO2
Yellow LED (Wifi): PIN 23 / GPIO0
Blue LED (BT/BLE): PIN 25 / GPIO16
*/
#endif
@@ -0,0 +1,8 @@
[env:heltec_wireless_bridge]
board = esp32dev
build_flags =
${common.build_flags}
-D HELTEC_WIRELESS_BRIDGE
lib_deps =
${common.lib_deps}
${common.display_libs}