Compare commits

..

57 Commits

Author SHA1 Message Date
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
Ricardo Guzman (Richonguzman) 855c84c079 Merge pull request #320 from richonguzman/richonguzman-patch-5
Update build for Heltec wireless paper v1
2025-09-09 10:02:05 -03:00
Ricardo Guzman (Richonguzman) bb4df08f06 Update build for Heltec wireless paper v1 2025-09-09 09:56:26 -03:00
richonguzman 6d0e98f4a2 version Date update 2025-09-09 09:42:25 -03:00
richonguzman c5dcc4c7ab SensorRead with UEM fix 2025-09-08 21:28:54 -03:00
richonguzman 5c5c940d71 mDNS added 2025-09-08 19:00:23 -03:00
87 changed files with 1193 additions and 702 deletions
+3 -1
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
@@ -67,7 +69,7 @@ jobs:
chip: esp32s3 chip: esp32s3
- name: heltec_ht-ct62 - name: heltec_ht-ct62
chip: esp32c3 chip: esp32c3
- name: heltec_wireless_paper - name: heltec_wireless_paper_v1
chip: esp32s3 chip: esp32s3
- name: OE5HWN_MeshCom - name: OE5HWN_MeshCom
chip: esp32 chip: esp32
+21 -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,14 @@ ____________________________________________________
<br /> <br />
## Timeline (Versions): # Timeline (Versions):
- 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 in Digipeater Mode.
- 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.
+15 -8
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,
@@ -86,7 +90,8 @@
"topic": "", "topic": "",
"username": "", "username": "",
"password": "", "password": "",
"port": 1883 "port": 1883,
"beaconOverMqtt": false
}, },
"ota": { "ota": {
"username": "", "username": "",
@@ -101,12 +106,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
} }
} }
+405 -315
View File
@@ -344,6 +344,28 @@
</button> </button>
</div> </div>
</div> </div>
<div class="col-6 mt-3">
<label
for="startupDelay"
class="form-label"
>Startup Delay<small>(To Allow Router/Modem to start WiFiAP before connection)</small></label
>
<div class="input-group">
<input
type="number"
name="startupDelay"
id="startupDelay"
placeholder="0"
class="form-control"
step="1"
min="0"
max="5"
/>
<span class="input-group-text"
>minutes</span
>
</div>
</div>
</div> </div>
</div> </div>
<hr> <hr>
@@ -545,12 +567,33 @@
</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-12"> <div class="col-6">
<label <label
for="beacon.interval" for="beacon.interval"
class="form-label" class="form-label"
@@ -626,7 +669,7 @@
</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 them (* wild card allowed)</small>
</div> </div>
<div class="col-9 mt-2"> <div class="col-9">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<label <label
@@ -667,7 +710,7 @@
</h5> </h5>
<small>Define the Digipeater mode</small> <small>Define the Digipeater mode</small>
</div> </div>
<div class="col-9 mt-2"> <div class="col-9">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<label <label
@@ -706,13 +749,13 @@
id="digi.ecoMode" id="digi.ecoMode"
> >
<option value="0"> <option value="0">
OFF (Normal Mode - WiFiAP enabled) OFF (Normal Mode - WiFiAP and Serial Output enabled)
</option> </option>
<option value="1"> <option value="1">
Ultra Eco Mode (Sleep till Packet Rx (WiFiAP/WebUI & Display disabled)) Ultra Eco Mode (Sleep till Packet Rx (WiFiAP/WebUI & Display disabled))
</option> </option>
<option value="2"> <option value="2">
OFF (Normal Mode - WiFiAP disabled) OFF (Normal Mode - WiFiAP disabled but Serial Output still enabled)
</option> </option>
</select> </select>
</div> </div>
@@ -744,21 +787,6 @@
</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-6">
<div class="form-check form-switch">
<input
type="checkbox"
name="lora.txActive"
id="lora.txActive"
class="form-check-input"
/>
<label
for="lora.txActive"
class="form-label"
>Enable LoRa TX</label
>
</div>
</div>
<div class="col-6"> <div class="col-6">
<div class="form-check form-switch"> <div class="form-check form-switch">
<input <input
@@ -775,6 +803,40 @@
</div> </div>
</div> </div>
<div class="col-6"> <div class="col-6">
<div class="form-check form-switch">
<input
type="checkbox"
name="lora.txActive"
id="lora.txActive"
class="form-check-input"
/>
<label
for="lora.txActive"
class="form-label"
>Enable LoRa TX</label
>
</div>
</div>
<div class="col-6 mt-1">
<label
for="lora.rxFreq"
class="form-label">
Rx Frequency
</label>
<div class="input-group">
<input
type="text"
name="lora.rxFreq"
id="lora.rxFreq"
placeholder="433775000"
class="form-control"
/>
<span class="input-group-text"
>Hz
</span>
</div>
</div>
<div class="col-6 mt-1">
<label <label
for="lora.txFreq" for="lora.txFreq"
class="form-label" class="form-label"
@@ -802,136 +864,123 @@
</span> </span>
</div> </div>
</div> </div>
<div class="col-6"> <div class="col-6 mt-3">
<label <label
for="lora.rxFreq" for="lora.rxSpreadingFactor"
class="form-label">
Rx Frequency
</label>
<div class="input-group">
<input
type="text"
name="lora.rxFreq"
id="lora.rxFreq"
placeholder="433775000"
class="form-control"
/>
<span class="input-group-text"
>Hz
</span>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12 mb-4">
<label
for="action.speed"
class="form-label" class="form-label"
>Predefined speeds >Rx Spreading Factor
</label> </label>
<select <select
class="form-select form-select" class="form-select form-select"
name="action.speed" name="lora.rxSpreadingFactor"
id="action.speed" id="lora.rxSpreadingFactor"
>
<option value="300">
BW 125khz CR 4:5 SF 12 (Slow
Standard, 300bps)
</option>
<option value="244">
BW 125khz CR 4:6 SF 12 (244bps)
</option>
<option value="209">
BW 125khz CR 4:7 SF 12 (209bps)
</option>
<option value="183">
BW 125khz CR 4:8 SF 12 (183bps)
</option>
<option value="610">
BW 125khz CR 4:8 SF 10 (610bps)
</option>
<option value="1200">
BW 125khz CR 4:7 SF 9 (Fast
Standard, 1200bps)
</option>
<option value="">
User defined
</option>
</select>
</div>
<div class="col-5">
<label
for="lora.signalBandwidth"
class="form-label"
>Bandwidth
</label>
<div class="input-group">
<select
class="form-select form-select"
name="lora.signalBandwidth"
id="lora.signalBandwidth"
required=""
>
<option value="62500" selected>
62.5 kHz
</option>
<option value="125000" selected>
125 kHz
</option>
<option value="250000">
250 kHz
</option>
<option value="500000">
500 kHz
</option>
</select>
</div>
</div>
<div class="col-7">
<label
for="lora.spreadingFactor"
class="form-label"
>Spreading Factor
</label>
<select
class="form-select form-select"
name="lora.spreadingFactor"
id="lora.spreadingFactor"
required="" required=""
> >
<option value="7"> <option value="7">SF7 - Lowest battery usage</option>
SF7 - Lowest battery usage
</option>
<option value="8">SF8</option> <option value="8">SF8</option>
<option value="9">SF9</option> <option value="9">SF9</option>
<option value="10">SF10</option> <option value="10">SF10</option>
<option value="11">SF11</option> <option value="11">SF11</option>
<option value="12" selected> <option value="12" selected>SF12 - Highest sensitivity</option>
SF12 - Highest sensitivity
</option>
</select> </select>
</div> </div>
</div> <div class="col-6 mt-3">
<div class="row mt-3">
<div class="col-6">
<label <label
for="lora.codingRate4" for="lora.txSpreadingFactor"
class="form-label"> class="form-label"
Coding Rate >Tx Spreading Factor
</label> </label>
<select <select
class="form-select form-select" class="form-select form-select"
name="lora.codingRate4" name="lora.txSpreadingFactor"
id="lora.codingRate4" id="lora.txSpreadingFactor"
required="" required=""
> >
<option value="5">5</option> <option value="7">SF7 - Lowest battery usage</option>
<option value="8">SF8</option>
<option value="9">SF9</option>
<option value="10">SF10</option>
<option value="11">SF11</option>
<option value="12" selected>SF12 - Highest sensitivity</option>
</select>
</div>
<div class="col-6 mt-3">
<label
for="lora.rxCodingRate4"
class="form-label">
Rx Coding Rate
</label>
<select
class="form-select form-select"
name="lora.rxCodingRate4"
id="lora.rxCodingRate4"
required=""
>
<option value="5" selected>5</option>
<option value="6">6</option> <option value="6">6</option>
<option value="7">7</option> <option value="7">7</option>
<option value="8">8</option> <option value="8">8</option>
</select> </select>
</div> </div>
<div class="col-6"> <div class="col-6 mt-3">
<label
for="lora.txCodingRate4"
class="form-label">
Tx Coding Rate
</label>
<select
class="form-select form-select"
name="lora.txCodingRate4"
id="lora.txCodingRate4"
required=""
>
<option value="5" selected>5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
</select>
</div>
<div class="col-6 mt-3">
<label
for="lora.rxSignalBandwidth"
class="form-label"
>Rx Signal Bandwidth
</label>
<div class="input-group">
<select
class="form-select form-select"
name="lora.rxSignalBandwidth"
id="lora.rxSignalBandwidth"
required=""
>
<option value="62500">62.5 kHz</option>
<option value="125000" selected>125 kHz</option>
<option value="250000">250 kHz</option>
<option value="500000">500 kHz</option>
</select>
</div>
</div>
<div class="col-6 mt-3">
<label
for="lora.txSignalBandwidth"
class="form-label"
>Tx Signal Bandwidth
</label>
<div class="input-group">
<select
class="form-select form-select"
name="lora.txSignalBandwidth"
id="lora.txSignalBandwidth"
required=""
>
<option value="62500">62.5 kHz</option>
<option value="125000" selected>125 kHz</option>
<option value="250000">250 kHz</option>
<option value="500000">500 kHz</option>
</select>
</div>
</div>
<div class="col-6 mt-3">
<label <label
for="lora.power" for="lora.power"
class="form-label"> class="form-label">
@@ -953,7 +1002,7 @@
>dBm</span >dBm</span
> >
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@@ -1013,7 +1062,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row mt-2"> <div class="row mt-1">
<div class="col-6"> <div class="col-6">
<label <label
for="display.timeout" for="display.timeout"
@@ -1092,8 +1141,8 @@
Calculate voltage divider accordingly. Calculate voltage divider accordingly.
</small> </small>
</div> </div>
<div class="col-9 mt-2"> <div class="col-9">
<div class="row mt-2"> <div class="row">
<div class="col-6"> <div class="col-6">
<div class="form-check form-switch"> <div class="form-check form-switch">
<input <input
@@ -1122,7 +1171,7 @@
>(Send Voltage As Telemetry)</label >(Send Voltage As Telemetry)</label
> >
</div> </div>
<div class="form-check form-switch mt-3"> <div class="form-check form-switch">
<input <input
type="checkbox" type="checkbox"
name="battery.monitorInternalVoltage" name="battery.monitorInternalVoltage"
@@ -1274,7 +1323,7 @@
</h5> </h5>
<small>Define Wx telemetry</small> <small>Define Wx telemetry</small>
</div> </div>
<div class="col-9 mt-2"> <div class="col-9">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div class="form-check form-switch"> <div class="form-check form-switch">
@@ -1295,7 +1344,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row mt-3"> <div class="row mt-2">
<div class="col-6"> <div class="col-6">
<label for="wxsensor.heightCorrection" class="form-label" <label for="wxsensor.heightCorrection" class="form-label"
>Height Correction (Above Sea-Level)</label >Height Correction (Above Sea-Level)</label
@@ -1363,18 +1412,37 @@
> >
</div> </div>
<div class="col-lg-9 col-sm-12"> <div class="col-lg-9 col-sm-12">
<div class="form-check form-switch"> <div class="row">
<input <div class="col-6">
type="checkbox" <div class="form-check form-switch">
name="syslog.active" <input
id="syslog.active" type="checkbox"
class="form-check-input" name="syslog.active"
/> id="syslog.active"
<label class="form-check-input"
for="syslog.active" />
class="form-label" <label
>Enable syslog</label for="syslog.active"
> class="form-label"
>Enable syslog</label
>
</div>
</div>
<div class="col-6">
<div class="form-check form-switch">
<input
type="checkbox"
name="syslog.logBeaconOverTCPIP"
id="syslog.logBeaconOverTCPIP"
class="form-check-input"
/>
<label
for="syslog.logBeaconOverTCPIP"
class="form-label"
>Log Beacon over TCP/IP</label
>
</div>
</div>
</div> </div>
<div class="row mt-3"> <div class="row mt-3">
<div class="col-6"> <div class="col-6">
@@ -1405,21 +1473,7 @@
class="form-control" class="form-control"
/> />
</div> </div>
<div class="col-6">
<div class="form-check form-switch">
<input
type="checkbox"
name="syslog.logBeaconOverTCPIP"
id="syslog.logBeaconOverTCPIP"
class="form-check-input"
/>
<label
for="syslog.logBeaconOverTCPIP"
class="form-label"
>Log Beacon over TPCIP</label
>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -1540,7 +1594,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-check form-switch">
<input <input
type="checkbox" type="checkbox"
@@ -1555,7 +1609,24 @@
> >
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-6">
<div class="form-check form-switch">
<input
type="checkbox"
name="mqtt.beaconOverMqtt"
id="mqtt.beaconOverMqtt"
class="form-check-input"
/>
<label
for="mqtt.beaconOverMqtt"
class="form-label"
>Send (also) iGate Beacon</label
>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-6">
<label <label
for="mqtt.server" for="mqtt.server"
class="form-label" class="form-label"
@@ -1570,11 +1641,11 @@
/> />
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-6">
<label <label
for="mqtt.topic" for="mqtt.topic"
class="form-label" class="form-label"
>Topic</label >Topic <small>(Default is <strong>aprs-igate</strong>)</small></label
> >
<div class="input-group"> <div class="input-group">
<input <input
@@ -1585,11 +1656,10 @@
placeholder="aprs-igate" placeholder="aprs-igate"
/> />
</div> </div>
<div class="form-text">
Default is <strong>aprs-igate</strong>
</div>
</div> </div>
<div class="col-12"> </div>
<div class="row mt-3">
<div class="col-6">
<label <label
for="mqtt.username" for="mqtt.username"
class="form-label" class="form-label"
@@ -1604,7 +1674,7 @@
/> />
</div> </div>
</div> </div>
<div class="col-12 mt-3"> <div class="col-6">
<label <label
for="mqtt.password" for="mqtt.password"
class="form-label" class="form-label"
@@ -1619,11 +1689,13 @@
/> />
</div> </div>
</div> </div>
<div class="col-12 mt-3"> </div>
<div class="row mt-3">
<div class="col-6">
<label <label
for="mqtt.port" for="mqtt.port"
class="form-label" class="form-label"
>Port</label >Port <small>(Default is <strong>1883</strong>)</small></label
> >
<div class="input-group"> <div class="input-group">
<input <input
@@ -1637,9 +1709,6 @@
min="0" min="0"
/> />
</div> </div>
<div class="form-text">
Default is <strong>1883</strong>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -1667,9 +1736,9 @@
Reboot Time Reboot Time
</h5> </h5>
</div> </div>
<div class="col-9 mt-2"> <div class="col-9">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-6">
<div class="form-check form-switch"> <div class="form-check form-switch">
<input <input
type="checkbox" type="checkbox"
@@ -1684,8 +1753,6 @@
> >
</div> </div>
</div> </div>
</div>
<div class="row mt-3">
<div class="col-6"> <div class="col-6">
<label <label
for="other.rebootModeTime" for="other.rebootModeTime"
@@ -1740,49 +1807,55 @@
WiFi Auto AP WiFi Auto AP
</h5> </h5>
<small <small
>Add your password and WiFi AP timeout to >WiFi AP will start if there is no WiFi
auto access point. Auto AP will start if connection available. Timeout will count from
there is no WiFi connection. Timeout will startup or last client disconnected.</small
count from startup or last client
disconnected.</small
> >
</div> </div>
<div class="col-lg-9 col-sm-12"> <div class="col-9">
<div class="col-12"> <div class="row">
<label <div class="col-6">
for="wifi.autoAP.password" <label
class="form-label" for="wifi.autoAP.password"
>Password</label class="form-label"
> >Password</label
<input >
type="password" <div class="input-group">
name="wifi.autoAP.password" <input
id="wifi.autoAP.password" type="password"
class="form-control" name="wifi.autoAP.password"
placeholder="1234567890" id="wifi.autoAP.password"
required="" class="form-control"
/> placeholder="1234567890"
</div> required=""
<div class="col-12 mt-3"> />
<label </div>
for="wifi.autoAP.timeout" </div>
class="form-label" <div class="col-6">
>WiFi AP timeout to search again for available WiFi's <label
<small>(in minutes)</small></label for="wifi.autoAP.timeout"
> class="form-label"
<input >WiFiAP timeout (to search again)</label
type="number" >
name="wifi.autoAP.timeout" <div class="input-group">
id="wifi.autoAP.timeout" <input
class="form-control" type="number"
placeholder="10" name="wifi.autoAP.timeout"
required="" id="wifi.autoAP.timeout"
step="1" class="form-control"
min="0" placeholder="10"
/> required=""
<div class="form-text"> step="1"
Set to <strong>0</strong> if you don't min="0"
want WiFi AP to stop. />
<span class="input-group-text"
>minutes</span
>
<div class="form-text">
Set to <strong>0</strong> if you don't
want WiFi AP to stop.
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -1813,27 +1886,29 @@
> >
</div> </div>
<div class="col-lg-9 col-sm-12"> <div class="col-lg-9 col-sm-12">
<div class="col-12"> <div class="row">
<label for="ota.username" class="form-label" <div class="col-6">
>Username</label <label for="ota.username" class="form-label"
> >Username</label
<input >
type="text" <input
name="ota.username" type="text"
id="ota.username" name="ota.username"
class="form-control" id="ota.username"
/> class="form-control"
</div> />
<div class="col-12 mt-3"> </div>
<label for="ota.password" class="form-label" <div class="col-6">
>Password</label <label for="ota.password" class="form-label"
> >Password</label
<input >
type="password" <input
name="ota.password" type="password"
id="ota.password" name="ota.password"
class="form-control" id="ota.password"
/> class="form-control"
/>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -1863,46 +1938,46 @@
> >
</div> </div>
<div class="col-lg-9 col-sm-12"> <div class="col-lg-9 col-sm-12">
<div class="row"> <div class="col-6">
<div class="col-12"> <div class="form-check form-switch">
<div class="form-check form-switch"> <input
<input type="checkbox"
type="checkbox" name="webadmin.active"
name="webadmin.active" id="webadmin.active"
id="webadmin.active" class="form-check-input"
class="form-check-input" />
/> <label
<label for="webadmin.active"
for="webadmin.active" class="form-label"
class="form-label" >Web interface authentication</label
>Web interface authentication</label >
>
</div>
</div> </div>
</div> </div>
<div class="col-12"> <div class="row">
<label for="webadmin.username" class="form-label" <div class="col-6">
>Username</label <label for="webadmin.username" class="form-label"
> >Username</label
<input >
type="text" <input
name="webadmin.username" type="text"
id="webadmin.username" name="webadmin.username"
class="form-control" id="webadmin.username"
value="admin" class="form-control"
required="" value="admin"
/> required=""
</div> />
<div class="col-12 mt-3"> </div>
<label for="webadmin.password" class="form-label" <div class="col-6">
>Password</label <label for="webadmin.password" class="form-label"
> >Password</label
<input >
type="password" <input
name="webadmin.password" type="password"
id="webadmin.password" name="webadmin.password"
class="form-control" id="webadmin.password"
/> class="form-control"
/>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -1946,21 +2021,19 @@
/> />
</div> </div>
</div> </div>
<div class="row"> <div class="col-12 mt-3">
<div class="col-12"> <div class="form-check form-switch">
<div class="form-check form-switch"> <input
<input type="checkbox"
type="checkbox" name="remoteManagement.rfOnly"
name="remoteManagement.rfOnly" id="remoteManagement.rfOnly"
id="remoteManagement.rfOnly" class="form-check-input"
class="form-check-input" />
/> <label
<label for="remoteManagement.rfOnly"
for="remoteManagement.rfOnly" class="form-label"
class="form-label" >Managers commands only via RF (not APRS-IS)</label
>Managers commands only via RF (not APRS-IS)</label >
>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -1990,26 +2063,43 @@
</small> </small>
</div> </div>
<div class="col-lg-9 col-sm-12"> <div class="col-lg-9 col-sm-12">
<div class="col-12"> <div class="row">
<label <div class="col-6">
for="ntp.gmtCorrection" <label
class="form-label" for="ntp.server"
>GMT Time Correction for accurate Local Time</label class="form-label"
> >NTP Server hostname</label
<div class="input-group">
<input
type="number"
name="ntp.gmtCorrection"
id="ntp.gmtCorrection"
placeholder="0"
class="form-control"
step="0.25"
min="-23.75"
max="23.75"
/>
<span class="input-group-text"
>hours</span
> >
<div class="input-group">
<input
type="text"
name="ntp.server"
id="ntp.server"
class="form-control"
/>
</div>
</div>
<div class="col-6">
<label
for="ntp.gmtCorrection"
class="form-label"
>GMT Time Correction Offset</label
>
<div class="input-group">
<input
type="number"
name="ntp.gmtCorrection"
id="ntp.gmtCorrection"
placeholder="0"
class="form-control"
step="0.25"
min="-23.75"
max="23.75"
/>
<span class="input-group-text"
>hours</span
>
</div>
</div> </div>
</div> </div>
</div> </div>
+31 -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
@@ -207,12 +215,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 +251,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 +309,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 +395,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 +469,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

+19 -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;
}; };
@@ -140,6 +144,7 @@ public:
class NTP { class NTP {
public: public:
String server;
float gmtCorrection; float gmtCorrection;
}; };
@@ -157,6 +162,7 @@ public:
String username; String username;
String password; String password;
int port; int port;
bool beaconOverMqtt;
}; };
class Configuration { class Configuration {
@@ -166,6 +172,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 +192,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 -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.
+4 -10
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-02"; 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();
+238 -118
View File
@@ -26,138 +26,157 @@
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["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 +192,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 +218,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 +241,147 @@ 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")) 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;
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 +392,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 +407,7 @@ bool Configuration::readFile() {
} }
} }
void Configuration::init() { void Configuration::setDefaultValues() {
WiFi_AP wifiap; WiFi_AP wifiap;
wifiap.ssid = ""; wifiap.ssid = "";
@@ -305,6 +415,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 +436,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 +455,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;
@@ -386,6 +503,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 +515,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 +538,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();
} }
+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";
} }
+11 -12
View File
@@ -296,18 +296,6 @@ namespace POWER_Utils {
adc_ctrl_OFF(); adc_ctrl_OFF();
#endif #endif
#if defined(HELTEC_WIRELESS_TRACKER)
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WS) || defined(LIGHTGATEWAY_1_0) || defined(LIGHTGATEWAY_PLUS_1_0) || defined(TTGO_LORA32_T3S3_V1_2) || defined(HELTEC_V2)
Wire.begin(OLED_SDA, OLED_SCL);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WP_V1) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#if defined(TTGO_T_DECK_GPS) || defined(TTGO_T_DECK_PLUS) #if defined(TTGO_T_DECK_GPS) || defined(TTGO_T_DECK_PLUS)
pinMode(BOARD_POWERON, OUTPUT); pinMode(BOARD_POWERON, OUTPUT);
digitalWrite(BOARD_POWERON, HIGH); digitalWrite(BOARD_POWERON, HIGH);
@@ -321,9 +309,20 @@ namespace POWER_Utils {
digitalWrite(TFT_CS, HIGH); digitalWrite(TFT_CS, HIGH);
delay(500); delay(500);
#endif
#ifdef USE_WIRE_WITH_OLED_PINS
Wire.begin(OLED_SDA, OLED_SCL);
#endif
#ifdef USE_WIRE_WITH_BOARD_I2C_PINS
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL); Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif #endif
#ifdef USE_WIRE1_WITH_BOARD_I2C_PINS
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
delay(1000); delay(1000);
BATTERY_Utils::setup(); BATTERY_Utils::setup();
BATTERY_Utils::startupBatteryHealth(); BATTERY_Utils::startupBatteryHealth();
+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);
} }
} }
+13
View File
@@ -17,10 +17,12 @@
*/ */
#include <WiFi.h> #include <WiFi.h>
#include "ESPmDNS.h"
#include "configuration.h" #include "configuration.h"
#include "station_utils.h" #include "station_utils.h"
#include "kiss_protocol.h" #include "kiss_protocol.h"
#include "kiss_utils.h" #include "kiss_utils.h"
#include "tnc_utils.h"
#include "utils.h" #include "utils.h"
@@ -45,6 +47,17 @@ namespace TNC_Utils {
if (Config.tnc.enableServer && Config.digi.ecoMode == 0) { if (Config.tnc.enableServer && Config.digi.ecoMode == 0) {
tncServer.stop(); tncServer.stop();
tncServer.begin(); tncServer.begin();
String host = "igate-" + Config.callsign;
if (!MDNS.begin(host.c_str())) {
Serial.println("Error Starting mDNS");
tncServer.stop();
return;
}
if (!MDNS.addService("tnc", "tcp", TNC_PORT)) {
Serial.println("Error: Could not add mDNS service");
}
Serial.println("TNC server started successfully");
Serial.println("mDNS Host: " + host + ".local");
} }
} }
+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);
}
}
} }
+124 -75
View File
@@ -115,159 +115,208 @@ 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.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) {
+1
View File
@@ -71,6 +71,7 @@ namespace WX_Utils {
#endif #endif
err = Wire.endTransmission(); err = Wire.endTransmission();
#endif #endif
delay(5);
if (err == 0) { if (err == 0) {
//Serial.println(addr); //this shows any connected board to I2C //Serial.println(addr); //this shows any connected board to I2C
if (addr == 0x76 || addr == 0x77) { // BME or BMP if (addr == 0x76 || addr == 0x77) { // BME or BMP
@@ -32,6 +32,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_NUM_3 #define GPIO_WAKEUP_PIN GPIO_NUM_3
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -34,6 +34,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_12 #define GPIO_WAKEUP_PIN GPIO_SEL_12
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -34,8 +34,11 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_12 #define GPIO_WAKEUP_PIN GPIO_SEL_12
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
#undef OLED_SDA #undef OLED_SDA
#undef OLED_SCL #undef OLED_SCL
@@ -34,6 +34,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_12 #define GPIO_WAKEUP_PIN GPIO_SEL_12
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -34,6 +34,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_33 #define GPIO_WAKEUP_PIN GPIO_SEL_33
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
+3
View File
@@ -30,6 +30,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26 #define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -30,6 +30,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26 #define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -28,6 +28,9 @@
#define RADIO_RST_PIN 0 #define RADIO_RST_PIN 0
#define RADIO_BUSY_PIN 32 #define RADIO_BUSY_PIN 32
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -28,6 +28,9 @@
#define RADIO_RST_PIN 0 #define RADIO_RST_PIN 0
#define RADIO_BUSY_PIN 32 #define RADIO_BUSY_PIN 32
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
+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}
+3
View File
@@ -34,6 +34,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_33 #define GPIO_WAKEUP_PIN GPIO_SEL_33
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -34,6 +34,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_5 #define GPIO_WAKEUP_PIN GPIO_SEL_5
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -35,6 +35,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_5 #define GPIO_WAKEUP_PIN GPIO_SEL_5
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
+3
View File
@@ -30,6 +30,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26 #define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -31,6 +31,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_12 #define GPIO_WAKEUP_PIN GPIO_SEL_12
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -30,7 +30,10 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_25 #define GPIO_WAKEUP_PIN GPIO_SEL_25
// Display // I2C
#define USE_WIRE_WITH_OLED_PINS
// Display
#define HAS_DISPLAY #define HAS_DISPLAY
#undef OLED_SDA #undef OLED_SDA
@@ -30,6 +30,11 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_38 #define GPIO_WAKEUP_PIN GPIO_SEL_38
// I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 11
#define BOARD_I2C_SCL 12
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 15 #define INTERNAL_LED_PIN 15
@@ -36,5 +36,10 @@
#define BUTTON_PIN 21 #define BUTTON_PIN 21
#define INTERNAL_LED_PIN 48 #define INTERNAL_LED_PIN 48
// I2C
#define USE_WIRE_WITH_OLED_PINS
#define OLED_SDA 5
#define OLED_SCL 6
#endif #endif
+3
View File
@@ -30,6 +30,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26 #define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -31,6 +31,12 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -48,7 +54,5 @@
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36 #define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL 37
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#endif #endif
@@ -31,6 +31,12 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -48,7 +54,5 @@
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36 #define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL 37
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#endif #endif
@@ -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}
@@ -31,6 +31,11 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
#define HAS_EPAPER #define HAS_EPAPER
@@ -46,7 +51,5 @@
#define BATTERY_PIN 20 #define BATTERY_PIN 20
#define ADC_CTRL 19 #define ADC_CTRL 19
#define VEXT_CTRL 45 #define VEXT_CTRL 45
#define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36
#endif #endif
@@ -31,6 +31,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -31,12 +31,15 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36 #define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL 37
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#endif #endif
@@ -31,6 +31,11 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
#define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin)
@@ -40,7 +45,5 @@
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36 #define VEXT_CTRL 36
#define ADC_CTRL 37 #define ADC_CTRL 37
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#endif #endif
@@ -30,6 +30,11 @@
#define RADIO_BUSY_PIN 13 // SX1262 BUSY #define RADIO_BUSY_PIN 13 // SX1262 BUSY
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 7
#define BOARD_I2C_SCL 6
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -40,8 +45,6 @@
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define ADC_CTRL 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1 #define ADC_CTRL 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1
#define VEXT_CTRL 3 // To turn on GPS and TFT #define VEXT_CTRL 3 // To turn on GPS and TFT
#define BOARD_I2C_SDA 7
#define BOARD_I2C_SCL 6
// GPS // GPS
#define HAS_GPS #define HAS_GPS
+5 -2
View File
@@ -30,6 +30,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26 #define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -43,7 +46,7 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 25 // Green Led #define INTERNAL_LED_PIN 25 // Green Led
#define BATTERY_PIN 35 #define BATTERY_PIN 35
#define HAS_ADC_CALIBRATION #define HAS_ADC_CALIBRATION
#endif #endif
@@ -30,6 +30,9 @@
#define RADIO_WAKEUP_PIN RADIO_BUSY_PIN #define RADIO_WAKEUP_PIN RADIO_BUSY_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_26 #define GPIO_WAKEUP_PIN GPIO_SEL_26
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
@@ -31,6 +31,9 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_33 #define GPIO_WAKEUP_PIN GPIO_SEL_33
// I2C
#define USE_WIRE_WITH_OLED_PINS
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
+5 -3
View File
@@ -31,6 +31,11 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_45 #define GPIO_WAKEUP_PIN GPIO_SEL_45
// I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
#define HAS_TFT #define HAS_TFT
@@ -50,7 +55,4 @@
#define BOARD_SDCARD_CS 39 #define BOARD_SDCARD_CS 39
#define BOARD_BL_PIN 42 #define BOARD_BL_PIN 42
#define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8
#endif #endif
+5 -3
View File
@@ -31,6 +31,11 @@
#define RADIO_WAKEUP_PIN RADIO_DIO1_PIN #define RADIO_WAKEUP_PIN RADIO_DIO1_PIN
#define GPIO_WAKEUP_PIN GPIO_SEL_45 #define GPIO_WAKEUP_PIN GPIO_SEL_45
// I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS
#define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8
// Display // Display
#define HAS_DISPLAY #define HAS_DISPLAY
#define HAS_TFT #define HAS_TFT
@@ -51,7 +56,4 @@
#define BOARD_SDCARD_CS 39 #define BOARD_SDCARD_CS 39
#define BOARD_BL_PIN 42 #define BOARD_BL_PIN 42
#define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8
#endif #endif