Compare commits

..

63 Commits

Author SHA1 Message Date
richonguzman
61db6c3132 backUpDigiMode and BME for HWSL v3 fix 2024-08-13 17:56:27 -04:00
richonguzman
9521a357b1 readmeUpdate 2024-08-13 14:49:30 -04:00
richonguzman
ee95931f00 web user and password 2024-08-13 14:48:08 -04:00
richonguzman
60aa2b05ac more boards update 2024-08-13 12:46:20 -04:00
richonguzman
bc5183a192 Ht-ct62 updates 2024-08-13 12:36:37 -04:00
richonguzman
1019306c7c wide2-n fix 2024-08-12 13:49:58 -04:00
richonguzman
fbe00903ad version Date on footer added 2024-08-12 11:01:35 -04:00
richonguzman
291a6bc80e added mesh - diy board v1-2 2024-08-12 10:35:45 -04:00
richonguzman
3b550c7f81 mode3 fix WIDE2-2 2024-08-06 10:57:00 -04:00
richonguzman
4659f8b2ff mode3start 2024-08-06 10:11:50 -04:00
richonguzman
62d157d7f0 state add at boot 2024-08-06 09:12:01 -04:00
richonguzman
b0e116ee1d Readme Update Digis 2024-08-05 17:42:59 -04:00
richonguzman
00b12c2bf5 version update 2024-08-05 15:43:42 -04:00
richonguzman
85b21565db index fix 2024-08-05 15:43:02 -04:00
richonguzman
b9e2c0e8f0 digimode 3 improvement 2024-08-05 15:42:33 -04:00
richonguzman
b763b4af78 RNAAAA add + WIDE2 description in index 2024-08-05 15:20:58 -04:00
richonguzman
5553e7ae5c added mode 3 for digirepeater 2024-08-05 14:37:16 -04:00
richonguzman
1afd039c3f digi mode 3 added 2024-08-03 21:55:32 -04:00
richonguzman
1888084f31 WSL v3 wire1 add 2024-08-02 16:15:10 -04:00
richonguzman
dc92b822c8 fixed missing wire begin 2024-08-02 15:28:31 -04:00
richonguzman
3c305259e0 update to recover from wifi AP 2024-08-02 13:08:54 -04:00
richonguzman
497d648c17 ready for testing 2024-07-18 14:41:09 -04:00
richonguzman
d267f6699c HWSL_V3_Display add 2024-07-17 16:20:20 -04:00
richonguzman
16ce6bc6d2 a7670 voltage calibration fix 2024-07-17 10:47:42 -04:00
richonguzman
008b6250ea Non Ham mods only for Rx 2024-07-10 15:13:57 -04:00
richonguzman
ddb83d1368 voltageCalibrationCorrection 2024-07-10 09:49:13 -04:00
richonguzman
26e2dec2b2 font size update 2024-07-09 10:41:26 -04:00
richonguzman
174507377b fix for other boards 2024-07-09 08:39:59 -04:00
richonguzman
864ed44a5d favicon and battery adc calibration 2024-07-08 23:29:04 -04:00
richonguzman
5d69cfbe1c 1 2024-07-08 23:06:03 -04:00
richonguzman
e57d356fd1 new ADC calibration test 2024-07-08 23:02:45 -04:00
richonguzman
8381f0916c variable name change 2024-07-05 13:12:21 -04:00
richonguzman
beca09293a queryUppercase fix 2024-07-05 11:58:18 -04:00
richonguzman
dcca18eeac readme Update 2024-07-01 18:30:11 -04:00
richonguzman
2494acea55 espacio en blanco 2024-06-30 10:36:15 -04:00
richonguzman
0c50ce8de4 tyeofpacket update 2024-06-30 09:24:21 -04:00
richonguzman
2f07d35861 readmeupdate7 2024-06-28 16:20:07 -04:00
richonguzman
91240c5be6 readmeupdate6 2024-06-28 16:19:18 -04:00
richonguzman
b4308a95d5 readmeupdate5 2024-06-28 16:18:41 -04:00
richonguzman
6c301795d6 readmeupdate4 2024-06-28 16:18:13 -04:00
richonguzman
5f0c6f4986 readmeupdate3 2024-06-28 16:15:56 -04:00
richonguzman
7c989e6e9e readmeupdate2 2024-06-28 16:15:22 -04:00
richonguzman
2bcda6d3a4 readme update 2024-06-28 16:14:42 -04:00
richonguzman
848492dc36 updated QueryAnswer for 3rdPartyPacket 2024-06-28 16:05:04 -04:00
richonguzman
413bef67fb readme update 2024-06-27 16:25:58 -04:00
richonguzman
3fa4c9371a new battery web config 2024-06-27 16:02:20 -04:00
richonguzman
e846c38f97 externalBatdivider 2024-06-27 15:39:53 -04:00
richonguzman
b8446e3f1d bat and sh gone 2024-06-27 13:19:51 -04:00
richonguzman
c3984bc8da casi listo para prueba 2024-06-26 23:42:24 -04:00
richonguzman
601b72da9f funciona 2024-06-26 18:13:02 -04:00
richonguzman
5d9493314d casi 2024-06-26 17:56:11 -04:00
richonguzman
86cf12d6c1 carga datos base 2024-06-26 17:10:07 -04:00
richonguzman
e5e2c6a980 readmeUpdate 2024-06-26 13:26:17 -04:00
richonguzman
3b9d49c5f9 personalNote implementation 2024-06-26 13:24:36 -04:00
richonguzman
ab9443140b personalNote1 2024-06-26 13:05:45 -04:00
richonguzman
ad1129c588 callsign validation process fix 2024-06-25 16:36:49 -04:00
richonguzman
8bb0b0446c more 3rd party filtering 2024-06-24 13:25:30 -04:00
richonguzman
6b1d319901 fix firstColon on last position 2024-06-24 11:36:40 -04:00
richonguzman
1ceaf159ba colonIndex fix3 2024-06-24 11:18:42 -04:00
richonguzman
f1de8d2df0 colonIndex upload fix 2024-06-24 11:16:52 -04:00
richonguzman
b9b4f46c66 typeOfPacket fix3 2024-06-24 11:02:38 -04:00
richonguzman
22b2c679d2 typeofPacket initial fix 2024-06-24 10:54:21 -04:00
richonguzman
7baa98bf7e first 3rdparty correction 2024-06-24 10:32:58 -04:00
31 changed files with 784 additions and 402 deletions

View File

@@ -23,6 +23,8 @@ jobs:
chip: esp32s3
- name: heltec_wireless_stick_lite_v3
chip: esp32s3
- name: heltec_wireless_stick_lite_v3_display
chip: esp32s3
- name: ESP32_DIY_LoRa
chip: esp32
- name: ESP32_DIY_LoRa_915
@@ -31,6 +33,8 @@ jobs:
chip: esp32
- name: ESP32_DIY_1W_LoRa_915
chip: esp32
- name: ESP32_DIY_1W_LoRa_Mesh_V1_2
chip: esp32
- name: ttgo-t-beam-v1_2
chip: esp32
- name: ttgo-t-beam-v1_2_915
@@ -61,6 +65,8 @@ jobs:
chip: esp32c3
- name: esp32c3_DIY_1W_LoRa_915
chip: esp32c3
- name: ESP32_C3_OctopusLab_LoRa
chip: esp32c3
steps:
- uses: actions/checkout@v3

View File

@@ -1,31 +1,27 @@
# Richonguzman / CA2RXU LoRa APRS iGate/Digirepeater
# CA2RXU LoRa APRS iGate/Digirepeater
This firmware is for using ESP32 based boards with LoRa Modules and GPS to live in the APRS world.
![Screenshot](https://github.com/richonguzman/LoRa_APRS_iGate/blob/main/images/iGateOledScreen.jpeg)
__(This iGate Firmware works with all LoRa Tracker Firmwares (specially this <a href="https://github.com/richonguzman/LoRa_APRS_Tracker" target="_blank">LoRa APRS Tracker Firmware</a>))__
___________________________________________________
<br />
## 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)
____________________________________________________
<br />
# WEB FLASHER/INSTALLER is <a href="https://richonguzman.github.io/lora-igate-web-flasher/installer.html" target="_blank">here</a>
____________________________________________________
<br />
# WIKI
### 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
@@ -47,10 +43,16 @@ ____________________________________________________
- Wemos Lolin32 Oled + SX1278 DIY Version.
____________________________________________________
<br />
## Timeline (Versions):
- 2024.06.21 Tx packets coming from APRS-IS are (now) formatted into 3rd Party (as they should have been since the beginning).
- 2024.08.13 Web Authentication for WebUI. Thanks Mitja S57PNX.
- 2024.08.05 WIDE2-n added to WIDE1-n in Digirepeater Modes.
- 2024.06.27 External Voltage Divider Resistor configuration on WebUI. Thanks Tilen S54B.
- 2024.06.26 Personal Note information on WebUI for the Station. Thanks Tilen S54B.
- 2024.06.24 Callsign Validation fix. Thanks Helge SA7SKY.
- 2024.06.21 Tx packets coming from APRS-IS are (now) formatted into 3rd Party (as they should have been since the beginning). Thanks Lynn KJ4ERJ and Geoffrey F4FXL.
- 2024.06.18 All boards with 433 / 868 / 915 MHz versions.
- 2024.06.10 ESP32C3 + 1W LoRa Module (E22 400M30S) support added.
- 2024.06.09 Si7021 module added (with autodetected I2C Address)

View File

@@ -52,7 +52,9 @@
"sendExternalVoltage": false,
"externalVoltagePin": 34,
"monitorExternalVoltage": false,
"externalSleepVoltage": 10.9
"externalSleepVoltage": 10.9,
"voltageDividerR1": 100.0,
"voltageDividerR2": 27.0
},
"bme": {
"active": false,
@@ -73,6 +75,10 @@
"username": "",
"password": ""
},
"webadmin": {
"username": "admin",
"password": ""
},
"other": {
"rememberStationTime": 30,
"lowPowerMode": false,
@@ -80,5 +86,6 @@
"backupDigiMode": false,
"rebootMode": false,
"rebootModeTime": 6
}
},
"personalNote": ""
}

BIN
data_embed/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

View File

@@ -6,6 +6,7 @@
<title>LoRa iGate & Digi software &minus; Ricardo Guzman CA2RXU</title>
<link rel="stylesheet" href="/bootstrap.css" />
<link rel="stylesheet" href="/style.css" />
<link rel="icon" href="/favicon.png" type="image/x-icon">
</head>
<body class="bg-body-tertiary">
<input type="file" accept="text/json,.json" style="display: none" />
@@ -15,7 +16,7 @@
>
<div class="container">
<a class="navbar-brand" href=""
>CA2RXU's LoRa</a
>CA2RXU's LoRa iGate</a
>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
@@ -107,10 +108,14 @@
Station
</h5>
<small
>Add your ham callsign and SSID. Optionally,
you can leave a comment describing your
station.</small
>
>Add your Ham callsign and SSID.
<br>
<br>
You can leave a comment describing your station.
<br>
<br>
In the bottom there is a field for personal note that can only be seen in WEB GUI.
</small>
</div>
<div class="col-lg-9 col-sm-12">
<div class="row">
@@ -237,6 +242,20 @@
class="form-control"
/>
</div>
<div class="col-12 mt-3">
<label
for="personalNote"
class="form-label"
>Personal Note</label
>
<input
type="text"
name="personalNote"
id="personalNote"
class="form-control"
placeholder="A Couple of words."
/>
</div>
</div>
</div>
</div>
@@ -474,8 +493,8 @@
for="beacon.sendViaAPRSIS"
class="form-label"
>Send our beacon to
APRS-IS</label
>
APRS-IS
</label>
</div>
</div>
<div class="col-6">
@@ -489,8 +508,8 @@
<label
for="beacon.sendViaRF"
class="form-label"
>Send beacon via RF</label
>
>Send beacon via RF
</label>
</div>
</div>
<div class="col-6 d-grid gap-2">
@@ -502,8 +521,8 @@
<label
for="beacon.interval"
class="form-label"
>Interval</label
>
>Interval
</label>
<div class="input-group">
<input
type="number"
@@ -516,8 +535,8 @@
min="1"
/>
<span class="input-group-text"
>minutes</span
>
>minutes
</span>
</div>
</div>
</div>
@@ -561,6 +580,9 @@
<option value="2">
WIDE1 (fill-in) Digi
</option>
<option value="3">
WIDE2 (+WIDE1) Digi
</option>
</select>
</div>
</div>
@@ -625,8 +647,8 @@
<label
for="lora.txFreq"
class="form-label"
>Tx Frequency</label
>
>Tx Frequency
</label>
<div class="input-group">
<input
type="text"
@@ -644,17 +666,17 @@
class="form-control"
required=""
/>
<span class="input-group-text"
>Hz</span
>
<span class="input-group-text">
Hz
</span>
</div>
</div>
<div class="col-6">
<label
for="lora.rxFreq"
class="form-label"
>Rx Frequency</label
>
class="form-label">
Rx Frequency
</label>
<div class="input-group">
<input
type="text"
@@ -664,8 +686,8 @@
class="form-control"
/>
<span class="input-group-text"
>Hz</span
>
>Hz
</span>
</div>
</div>
</div>
@@ -674,8 +696,8 @@
<label
for="action.speed"
class="form-label"
>Predefined speeds</label
>
>Predefined speeds
</label>
<select
class="form-select form-select"
name="action.speed"
@@ -710,8 +732,8 @@
<label
for="lora.signalBandwidth"
class="form-label"
>Bandwidth</label
>
>Bandwidth
</label>
<div class="input-group">
<select
class="form-select form-select"
@@ -735,8 +757,8 @@
<label
for="lora.spreadingFactor"
class="form-label"
>Spreading Factor</label
>
>Spreading Factor
</label>
<select
class="form-select form-select"
name="lora.spreadingFactor"
@@ -760,9 +782,9 @@
<div class="col-6">
<label
for="lora.codingRate4"
class="form-label"
>Coding Rate</label
>
class="form-label">
Coding Rate
</label>
<select
class="form-select form-select"
name="lora.codingRate4"
@@ -779,9 +801,9 @@
<div class="col-6">
<label
for="lora.power"
class="form-label"
>Power</label
>
class="form-label">
Power
</label>
<div class="input-group">
<input
type="number"
@@ -925,7 +947,15 @@
</svg>
Battery
</h5>
<small>Battery Monitor & Health</small>
<small>
Battery Monitor & Health
<br>
<br>
Max Voltage on input pin is 3.3V.
<br>
<br>
Calculate voltage divider accordingly.
</small>
</div>
<div class="col-9 mt-2">
<div class="row mt-2">
@@ -943,19 +973,6 @@
>Send Internal Voltage</label
>
</div>
<div class="form-check form-switch">
<input
type="checkbox"
name="battery.sendExternalVoltage"
id="battery.sendExternalVoltage"
class="form-check-input"
/>
<label
for="battery.sendExternalVoltage"
class="form-label"
>Send External Voltage</label
>
</div>
<div class="form-check form-switch mt-3">
<input
type="checkbox"
@@ -991,21 +1008,20 @@
</div>
</div>
<div class="col-6">
<div class="form-floating col-7">
<div class="form-check form-switch">
<input
type="text"
name="battery.externalVoltagePin"
id="battery.externalVoltagePin"
value="34"
class="form-control"
type="checkbox"
name="battery.sendExternalVoltage"
id="battery.sendExternalVoltage"
class="form-check-input"
/>
<label
for="battery.externalVoltagePin"
for="battery.sendExternalVoltage"
class="form-label"
>External Voltage Pin</label
>Send External Voltage</label
>
</div>
<div class="form-check form-switch mt-4">
<div class="form-check form-switch mt-3">
<input
type="checkbox"
name="battery.monitorExternalVoltage"
@@ -1038,6 +1054,52 @@
>
</div>
</div>
<div class="form-floating col-7 mt-3">
<input
type="text"
name="battery.externalVoltagePin"
id="battery.externalVoltagePin"
value="34"
class="form-control"
/>
<label
for="battery.externalVoltagePin"
class="form-label"
>External Voltage Pin</label
>
</div>
<div class="col">
<label for="battery.voltageDividerR1" class="form-label">External Voltage divider R1</label>
<div class="input-group">
<input
type="number"
name="battery.voltageDividerR1"
id="battery.voltageDividerR1"
placeholder="100.0"
class="form-control"
step="0.1"
min="1"
max="1000"
/>
<span class="input-group-text">kOhm</span>
</div>
</div>
<div class="col">
<label for="battery.voltageDividerR2" class="form-label">External Voltage divider R2</label>
<div class="input-group">
<input
type="number"
name="battery.voltageDividerR2"
id="battery.voltageDividerR2"
placeholder="27.0"
class="form-control"
step="0.1"
min="1"
max="1000"
/>
<span class="input-group-text">kOhm</span>
</div>
</div>
</div>
</div>
</div>
@@ -1061,7 +1123,7 @@
</svg>
Telemetry
</h5>
<small>Define the telemetry</small>
<small>Define Wx telemetry</small>
</div>
<div class="col-9 mt-2">
<div class="row">
@@ -1078,9 +1140,7 @@
class="form-label"
><b>Activate Wx Telemetry</b>
<small
>Requires a BME/BMP280 or
BME680 sensor
installed</small
>Requires a BME/BMP280, BME680 or Si7021 sensor installed</small
></label
>
</div>
@@ -1339,7 +1399,7 @@
type="number"
name="other.rebootModeTime"
id="other.rebootModeTime"
placeholder="0"
placeholder="6"
class="form-control"
step="6"
min="6"
@@ -1481,6 +1541,75 @@
</div>
<hr />
<div class="row my-5 d-flex align-items-top">
<div class="col-lg-3 col-sm-12">
<h5>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-cloud-upload-fill"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M8 0a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 4.095 0 5.555 0 7.318 0 9.366 1.708 11 3.781 11H7.5V5.707L5.354 7.854a.5.5 0 1 1-.708-.708l3-3a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 5.707V11h4.188C14.502 11 16 9.57 16 7.773c0-1.636-1.242-2.969-2.834-3.194C12.923 1.999 10.69 0 8 0m-.5 14.5V11h1v3.5a.5.5 0 0 1-1 0"
/>
</svg>
Admin
</h5>
<small
>Set your username and password to allow
access to the web interface.</small
>
</div>
<div class="col-lg-9 col-sm-12">
<div class="row">
<div class="col-12">
<div class="form-check form-switch">
<input
type="checkbox"
name="webadmin.active"
id="webadmin.active"
class="form-check-input"
/>
<label
for="webadmin.active"
class="form-label"
>Web interface authentication</label
>
</div>
</div>
</div>
<div class="col-12">
<label for="webadmin.username" class="form-label"
>Username</label
>
<input
type="text"
name="webadmin.username"
id="webadmin.username"
class="form-control"
value="admin"
required=""
/>
</div>
<div class="col-12 mt-3">
<label for="webadmin.password" class="form-label"
>Password</label
>
<input
type="password"
name="webadmin.password"
id="webadmin.password"
class="form-control"
/>
</div>
</div>
</div>
<hr />
<div class="row my-5 d-flex align-items-top">
<div class="col-lg-3 col-sm-12">
<h5>
@@ -1537,7 +1666,7 @@
<label
for="other.lowPowerMode"
class="form-label"
>Low power mode</label
>Low power mode (only for HT-CT62)</label
>
</div>
</div>
@@ -1702,4 +1831,4 @@
</body>
<script src="/bootstrap.js"></script>
<script src="/script.js"></script>
</html>
</html>

View File

@@ -79,7 +79,7 @@ function loadSettings(settings) {
document.getElementById("beacon.path").value = settings.beacon.path;
document.getElementById("beacon.symbol").value = settings.beacon.symbol;
document.getElementById("beacon.overlay").value = settings.beacon.overlay;
document.getElementById("personalNote").value = settings.personalNote;
document.getElementById("action.symbol").value = settings.beacon.overlay + settings.beacon.symbol;
document.querySelector(".list-networks").innerHTML = "";
@@ -162,6 +162,8 @@ function loadSettings(settings) {
document.getElementById("battery.internalSleepVoltage").value = settings.battery.internalSleepVoltage.toFixed(1);
document.getElementById("battery.sendExternalVoltage").checked = settings.battery.sendExternalVoltage;
document.getElementById("battery.externalVoltagePin").value = settings.battery.externalVoltagePin;
document.getElementById("battery.voltageDividerR1").value = settings.battery.voltageDividerR1.toFixed(1);
document.getElementById("battery.voltageDividerR2").value = settings.battery.voltageDividerR2.toFixed(1);
document.getElementById("battery.monitorExternalVoltage").checked = settings.battery.monitorExternalVoltage;
document.getElementById("battery.externalSleepVoltage").value = settings.battery.externalSleepVoltage.toFixed(1);
@@ -199,6 +201,11 @@ function loadSettings(settings) {
document.getElementById("ota.username").value = settings.ota.username;
document.getElementById("ota.password").value = settings.ota.password;
// Webadmin
document.getElementById("webadmin.active").checked = settings.webadmin.active;
document.getElementById("webadmin.username").value = settings.webadmin.username;
document.getElementById("webadmin.password").value = settings.webadmin.password;
// Experimental
document.getElementById("other.backupDigiMode").checked = settings.other.backupDigiMode;
@@ -271,8 +278,23 @@ function toggleFields() {
'input[name="battery.externalVoltagePin"]'
);
externalVoltagePinInput.disabled =
!sendExternalVoltageCheckbox.checked;
externalVoltagePinInput.disabled = !sendExternalVoltageCheckbox.checked;
voltageDividerR1.disabled = !sendExternalVoltageCheckbox.checked;
voltageDividerR2.disabled = !sendExternalVoltageCheckbox.checked;
const WebadminCheckbox = document.querySelector(
'input[name="webadmin.active"]'
);
const WebadminUsername = document.querySelector(
'input[name="webadmin.username"]'
);
const WebadminPassword = document.querySelector(
'input[name="webadmin.password"]'
);
WebadminUsername.disabled = !WebadminCheckbox.checked;
WebadminPassword.disabled = !WebadminCheckbox.checked;
}
const sendExternalVoltageCheckbox = document.querySelector(
@@ -282,8 +304,34 @@ const externalVoltagePinInput = document.querySelector(
'input[name="battery.externalVoltagePin"]'
);
const voltageDividerR1 = document.querySelector(
'input[name="battery.voltageDividerR1"]'
);
const voltageDividerR2 = document.querySelector(
'input[name="battery.voltageDividerR2"]'
);
sendExternalVoltageCheckbox.addEventListener("change", function () {
externalVoltagePinInput.disabled = !this.checked;
voltageDividerR1.disabled = !this.checked;
voltageDividerR2.disabled = !this.checked;
});
const WebadminCheckbox = document.querySelector(
'input[name="webadmin.active"]'
);
const WebadminUsername = document.querySelector(
'input[name="webadmin.username"]'
);
const WebadminPassword = document.querySelector(
'input[name="webadmin.password"]'
);
WebadminCheckbox.addEventListener("change", function () {
WebadminUsername.disabled = !this.checked;
WebadminPassword.disabled = !this.checked;
});
document.querySelector(".new button").addEventListener("click", function () {

View File

@@ -1,39 +0,0 @@
@echo off
echo Loading...
where /q python.exe
if %errorlevel% neq 0 (
echo "Python is not installed. Please install it and try again."
exit /b
)
where /q pip
if %errorlevel% neq 0 (
echo "pip is not installed. Please install it and try again."
exit /b
)
pip show pyserial >nul 2>&1
if %errorlevel% neq 0 (
echo "Installing pyserial..."
pip install pyserial
)
echo Your firmware will be upgraded without factory reset.
echo:
echo IF THIS IS YOUR FIRST FLASH ON THIS BOARD PLEASE USE install_with_factory_reset.bat INSTEAD!
echo:
echo Available COM ports:
python.exe -c "import serial.tools.list_ports; print('\n'.join([str(c) for c in serial.tools.list_ports.comports()]))"
echo:
set /p port="Enter COM port (for example COM5): "
python.exe ./bin/esptool/esptool.py --chip esp32 --port "%port%" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
pause

View File

@@ -1,15 +0,0 @@
#!/bin/bash
echo "Your firmware will be upgraded without factory reset."
echo "IF THIS IS YOUR FIRST FLASH ON THIS BOARD PLEASE USE install_with_factory_reset.sh INSTEAD!"
read -p "Enter COM port (for example /dev/ttyS5): " port
PYTHON_CMD=python
if command -v python3 &> /dev/null
then
PYTHON_CMD=python3
fi
PYTHON_CMD ./bin/esptool/esptool.py --chip esp32 --port "$port" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
echo "Firmware flashed"

View File

@@ -1,44 +0,0 @@
@echo off
echo Loading...
where /q python.exe
if %errorlevel% neq 0 (
echo "Python is not installed. Please install it and try again."
exit /b
)
where /q pip
if %errorlevel% neq 0 (
echo "pip is not installed. Please install it and try again."
exit /b
)
pip show pyserial >nul 2>&1
if %errorlevel% neq 0 (
echo "Installing pyserial..."
pip install pyserial
)
echo Your current configuration will be LOST!!!
echo Your current configuration will be LOST!!!
echo Your current configuration will be LOST!!!
echo:
echo If you already have this board flashed with our firmware please use install_upgrade.bat instead!
echo:
echo Available COM ports:
python.exe -c "import serial.tools.list_ports; print('\n'.join([str(c) for c in serial.tools.list_ports.comports()]))"
echo:
set /p port="Enter COM port (for example COM5): "
python.exe bin/esptool/esptool.py --chip esp32 --port "%port%" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 2686976 firmware/spiffs.bin
python.exe bin/esptool/esptool.py --chip esp32 --port "%port%" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
pause

View File

@@ -1,17 +0,0 @@
#!/bin/bash
echo "Your firmware will be upgraded without factory reset."
echo "IF THIS IS YOUR FIRST FLASH ON THIS BOARD PLEASE USE install_with_factory_reset.sh INSTEAD!"
read -p "Enter COM port (for example /dev/ttyS5): " port
PYTHON_CMD=python
if command -v python3 &> /dev/null
then
PYTHON_CMD=python3
fi
$PYTHON_CMD ./bin/esptool/esptool.py --chip esp32 --port "$port" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 2686976 firmware/spiffs.bin
$PYTHON_CMD ./bin/esptool/esptool.py --chip esp32 --port "$port" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
echo "Firmware flashed"

View File

@@ -22,6 +22,7 @@ board_build.embed_files =
data_embed/script.js.gz
data_embed/bootstrap.css.gz
data_embed/bootstrap.js.gz
data_embed/favicon.png.gz
extra_scripts =
pre:tools/compress.py
debug_tool = esp-prog
@@ -46,6 +47,7 @@ build_flags =
-Werror -Wall
-DTTGO_T_LORA32_V2_1
-DHAS_SX1278
-DHAS_ADC_CALIBRATION
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
@@ -58,6 +60,7 @@ build_flags =
-Werror -Wall
-DTTGO_T_LORA32_V2_1_915
-DHAS_SX1276
-DHAS_ADC_CALIBRATION
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
@@ -113,6 +116,17 @@ build_flags =
lib_deps =
${common.lib_deps}
[env:heltec_wireless_stick_lite_v3_display]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
-Werror -Wall
-DHELTEC_WSL_V3_DISPLAY
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
[env:ESP32_DIY_LoRa]
board = esp32dev
build_flags =
@@ -163,6 +177,20 @@ lib_deps =
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ESP32_DIY_1W_LoRa_Mesh_V1_2]
board = esp32dev
build_flags =
-Werror -Wall
-DESP32_DIY_1W_LoRa_Mesh_V1_2
-DHAS_SX1268
-DHAS_1W_LORA
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ttgo-t-beam-v1_2]
board = ttgo-t-beam
build_flags =
@@ -391,6 +419,22 @@ build_flags =
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ESP32_C3_OctopusLab_LoRa]
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
build_flags =
-Werror -Wall
-DESP32_C3_OctopusLab_LoRa
-DHAS_SX1268
-DRADIO_HAS_XTAL
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9

View File

@@ -21,6 +21,7 @@ ________________________________________________________________________________
#include "aprs_is_utils.h"
#include "station_utils.h"
#include "boards_pinout.h"
#include "battery_utils.h"
#include "syslog_utils.h"
#include "query_utils.h"
#include "power_utils.h"
@@ -37,7 +38,7 @@ ________________________________________________________________________________
#include "A7670_utils.h"
#endif
String versionDate = "2024.06.21";
String versionDate = "2024.08.13";
Configuration Config;
WiFiClient espClient;
@@ -60,6 +61,7 @@ String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seven
void setup() {
Serial.begin(115200);
POWER_Utils::setup();
BATTERY_Utils::setup();
Utils::setupDisplay();
Config.check();
LoRa_Utils::setup();
@@ -96,7 +98,7 @@ void setup() {
String comment = Config.beacon.comment;
if (Config.battery.sendInternalVoltage) comment += " Batt=" + String(BATTERY_Utils::checkInternalVoltage(),2) + "V";
if (Config.battery.sendExternalVoltage) comment += " Ext=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V";
STATION_Utils::addToOutputPacketBuffer(GPS_Utils::getiGateLoRaBeaconPacket() + comment);
LoRa_Utils::sendNewPacket(GPS_Utils::getiGateLoRaBeaconPacket() + comment);
lastBeacon = time;
}
@@ -161,7 +163,7 @@ void loop() {
APRS_IS_Utils::processLoRaPacket(packet); // Send received packet to APRSIS
}
if (Config.digi.mode == 2 || backUpDigiMode) { // If Digi enabled
if (Config.digi.mode == 2 || Config.digi.mode == 3 || backUpDigiMode) { // If Digi enabled
STATION_Utils::clean25SegBuffer();
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
}
@@ -178,7 +180,7 @@ void loop() {
APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS
}
STATION_Utils::processOutputPacketBuffer();
STATION_Utils::processOutputPacketBuffer();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
Utils::checkRebootTime();

View File

@@ -55,13 +55,13 @@ namespace APRS_IS_Utils {
Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) + ")");
// String filter = "t/m/" + Config.callsign + "/" + (String)Config.aprs_is.reportingDistance;
String aprsauth = "user ";
aprsauth += Config.callsign;
aprsauth += " pass ";
aprsauth += Config.aprs_is.passcode;
aprsauth += " vers CA2RXU_LoRa_iGate 1.3 filter ";
aprsauth += Config.aprs_is.filter;
upload(aprsauth);
String aprsAuth = "user ";
aprsAuth += Config.callsign;
aprsAuth += " pass ";
aprsAuth += Config.aprs_is.passcode;
aprsAuth += " vers CA2RXU_LoRa_iGate 1.4 filter ";
aprsAuth += Config.aprs_is.filter;
upload(aprsAuth);
delay(200);
}
}
@@ -129,6 +129,89 @@ namespace APRS_IS_Utils {
return buildedPacket;
}
bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty) {
String receivedMessage;
if (packet.indexOf("{") > 0) { // ack?
String ackMessage = "ack";
ackMessage.concat(packet.substring(packet.indexOf("{") + 1));
ackMessage.trim();
//Serial.println(ackMessage);
String addToBuffer = Config.callsign;
addToBuffer += ">APLRG1,RFONLY";
if (Config.beacon.path != "") {
addToBuffer += ",";
addToBuffer += Config.beacon.path;
}
addToBuffer += "::";
String processedSender = sender;
for (int i = sender.length(); i < 9; i++) {
processedSender += ' ';
}
addToBuffer += processedSender;
addToBuffer += ":";
addToBuffer += ackMessage;
STATION_Utils::addToOutputPacketBuffer(addToBuffer);
receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{"));
} else {
receivedMessage = packet.substring(packet.indexOf(":") + 1);
}
if (receivedMessage.indexOf("?") == 0) {
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
STATION_Utils::addToOutputPacketBuffer(QUERY_Utils::process(receivedMessage, sender, false, thirdParty));
lastScreenOn = millis();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0);
return true;
}
else {
return false;
}
}
void processLoRaPacket(const String& packet) {
if (espClient.connected() || modemLoggedToAPRSIS) {
if (packet != "") {
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) {
int firstColonIndex = packet.indexOf(":");
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] != '}' && packet.indexOf("TCPIP") == -1) {
const String& Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
bool queryMessage = false;
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage), false);
}
if (!queryMessage) {
const String& aprsPacket = buildPacketToUpload(packet);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
lastScreenOn = millis();
#ifdef HAS_A7670
stationBeacon = true;
A7670_Utils::uploadToAPRSIS(aprsPacket);
stationBeacon = false;
#else
upload(aprsPacket);
#endif
Utils::println("---> Uploaded to APRS-IS");
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
}
}
}
}
}
}
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType) {
String packet = aprsisPacket;
packet.trim();
@@ -174,86 +257,6 @@ namespace APRS_IS_Utils {
return outputPacket;
}
bool processReceivedLoRaMessage(const String& sender, const String& packet) {
String receivedMessage;
if (packet.indexOf("{") > 0) { // ack?
String ackMessage = "ack";
ackMessage.concat(packet.substring(packet.indexOf("{") + 1));
ackMessage.trim();
//Serial.println(ackMessage);
String addToBuffer = Config.callsign;
addToBuffer += ">APLRG1,RFONLY";
if (Config.beacon.path != "") {
addToBuffer += ",";
addToBuffer += Config.beacon.path;
}
addToBuffer += "::";
String processedSender = sender;
for (int i = sender.length(); i < 9; i++) {
processedSender += ' ';
}
addToBuffer += processedSender;
addToBuffer += ":";
addToBuffer += ackMessage;
STATION_Utils::addToOutputPacketBuffer(addToBuffer);
receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{"));
} else {
receivedMessage = packet.substring(packet.indexOf(":") + 1);
}
if (receivedMessage.indexOf("?") == 0) {
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
STATION_Utils::addToOutputPacketBuffer(QUERY_Utils::process(receivedMessage, sender, 0)); // LoRa
lastScreenOn = millis();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0);
return true;
}
else {
return false;
}
}
void processLoRaPacket(const String& packet) {
if (espClient.connected() || modemLoggedToAPRSIS) {
if (packet != "") {
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("}") == -1 && packet.indexOf("TCPIP") == -1) && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) {
const String& Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
bool queryMessage = false;
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage));
}
if (!queryMessage) {
const String& aprsPacket = buildPacketToUpload(packet);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
lastScreenOn = millis();
#ifdef HAS_A7670
stationBeacon = true;
A7670_Utils::uploadToAPRSIS(aprsPacket);
stationBeacon = false;
#else
upload(aprsPacket);
#endif
Utils::println("---> Uploaded to APRS-IS");
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
}
}
}
}
}
void processAPRSISPacket(const String& packet) {
if (!packet.startsWith("#")) {
if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) {
@@ -288,7 +291,7 @@ namespace APRS_IS_Utils {
}
if (receivedMessage.indexOf("?") == 0) {
Utils::println("Received Query APRS-IS : " + packet);
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, 1); // APRSIS
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, true, false);
//Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n")));
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);

View File

@@ -10,10 +10,12 @@ namespace APRS_IS_Utils {
void connect();
void checkStatus();
String checkForStartingBytes(const String& packet);
String buildPacketToUpload(const String& packet);
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType);
bool processReceivedLoRaMessage(const String& sender, const String& packet);
bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty);
void processLoRaPacket(const String& packet);
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType);
void processAPRSISPacket(const String& packet);
void listenAPRSIS();

View File

@@ -5,19 +5,41 @@
#include "power_utils.h"
#include "utils.h"
extern Configuration Config;
extern uint32_t lastBatteryCheck;
extern Configuration Config;
extern uint32_t lastBatteryCheck;
bool shouldSleepLowVoltage = false;
bool shouldSleepLowVoltage = false;
float adcReadingTransformation = (3.3/4095);
float voltageDividerCorrection = 0.288;
float adcReadingTransformation = (3.3/4095);
float voltageDividerCorrection = 0.288;
float readingCorrection = 0.125;
float multiplyCorrection = 0.035;
// for External Voltage Measurment (MAX = 15Volts !!!)
float R1 = 100.000; //in Kilo-Ohms
float R2 = 27.000; //in Kilo-Ohms
float readingCorrection = 0.125;
float multiplyCorrection = 0.035;
float voltageDividerTransformation = 0.0;
#ifdef HAS_ADC_CALIBRATION
#include <esp_adc_cal.h>
#if defined(TTGO_T_LORA32_V2_1) || defined(TTGO_T_LORA32_V2_1_915)
#define InternalBattery_ADC_Channel ADC1_CHANNEL_7 // t_lora32 pin35
#define ExternalVoltage_ADC_Channel ADC1_CHANNEL_6 // t_lora32 pin34
#endif
#if CONFIG_IDF_TARGET_ESP32
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32C3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32S3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT
#endif
esp_adc_cal_characteristics_t adc_chars;
#endif
bool calibrationEnable = false;
namespace BATTERY_Utils {
@@ -26,6 +48,46 @@ namespace BATTERY_Utils {
return (voltage - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void adcCalibration() {
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable) {
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(InternalBattery_ADC_Channel, ADC_ATTEN_DB_12);
adc1_config_channel_atten(ExternalVoltage_ADC_Channel, ADC_ATTEN_DB_12);
}
#endif
}
void adcCalibrationCheck() {
#ifdef HAS_ADC_CALIBRATION
esp_err_t ret;
ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME);
/*if (ret == ESP_ERR_NOT_SUPPORTED) {
Serial.println("Calibration scheme not supported, skip software calibration");
} else if (ret == ESP_ERR_INVALID_VERSION) {
Serial.println("eFuse not burnt, skip software calibration");
} else */
if (ret == ESP_OK) {
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, 1100, &adc_chars);
//Serial.printf("eFuse Vref:%u mV\n", adc_chars.vref);
calibrationEnable = true;
} /*else {
Serial.println("Invalid Calibration Arg");
}*/
#endif
}
void setup() {
if ((Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) && Config.battery.voltageDividerR2 != 0) voltageDividerTransformation = (Config.battery.voltageDividerR1 + Config.battery.voltageDividerR2) / Config.battery.voltageDividerR2;
#if defined(HAS_ADC_CALIBRATION)
if (Config.battery.sendInternalVoltage || Config.battery.monitorInternalVoltage || Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) {
adcCalibrationCheck();
adcCalibration();
}
#endif
}
float checkInternalVoltage() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
if(POWER_Utils::isBatteryConnected()) {
@@ -46,12 +108,23 @@ namespace BATTERY_Utils {
#endif
for (int i = 0; i < 100; i++) {
#ifdef BATTERY_PIN
sample = analogRead(BATTERY_PIN);
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_LoRa_915) || defined(ESP32_DIY_1W_LoRa) || defined(ESP32_DIY_1W_LoRa_915)
sample = 0;
#endif
#else
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
sample = adc1_get_raw(InternalBattery_ADC_Channel);
} else {
sample = analogRead(BATTERY_PIN);
}
#else
#ifdef BATTERY_PIN
sample = analogRead(BATTERY_PIN);
#else
sample = 0;
#endif
#endif
#endif
sampleSum += sample;
delayMicroseconds(50);
}
@@ -66,9 +139,19 @@ namespace BATTERY_Utils {
double inputDivider = (1.0 / (390.0 + 100.0)) * 100.0; // The voltage divider is a 390k + 100k resistor in series, 100k on the low side.
return (((sampleSum/100) * adcReadingTransformation) / inputDivider) + 0.285; // Yes, this offset is excessive, but the ADC on the ESP32s3 is quite inaccurate and noisy. Adjust to own measurements.
#else
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection; // raw voltage without mapping
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
float voltage = esp_adc_cal_raw_to_voltage(sampleSum / 100, &adc_chars);
voltage *= 2; // for 100K/100K voltage divider
voltage /= 1000;
return voltage;
} else {
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection; // raw voltage without mapping
}
#else
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection; // raw voltage without mapping
#endif
#endif
// return mapVoltage(voltage, 3.34, 4.71, 3.0, 4.2); // mapped voltage
#endif
}
@@ -77,14 +160,32 @@ namespace BATTERY_Utils {
int sample;
int sampleSum = 0;
for (int i = 0; i < 100; i++) {
sample = analogRead(Config.battery.externalVoltagePin);
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
sample = adc1_get_raw(ExternalVoltage_ADC_Channel);
} else {
sample = analogRead(Config.battery.externalVoltagePin);
}
#else
sample = analogRead(Config.battery.externalVoltagePin);
#endif
sampleSum += sample;
delayMicroseconds(50);
delayMicroseconds(50);
}
float voltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * ((R1+R2)/R2)) - multiplyCorrection;
float extVoltage;
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
extVoltage = esp_adc_cal_raw_to_voltage(sampleSum / 100, &adc_chars) * voltageDividerTransformation; // in mV
extVoltage /= 1000;
} else {
extVoltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * voltageDividerTransformation) - multiplyCorrection;
}
#else
extVoltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * voltageDividerTransformation) - multiplyCorrection;
#endif
return voltage; // raw voltage without mapping
return extVoltage; // raw voltage without mapping
// return mapVoltage(voltage, 5.05, 6.32, 4.5, 5.5); // mapped voltage
}

View File

@@ -6,6 +6,9 @@
namespace BATTERY_Utils {
void adcCalibration();
void adcCalibrationCheck();
void setup();
float checkInternalVoltage();
float checkExternalVoltage();
void checkIfShouldSleep(); // ????

View File

@@ -32,7 +32,7 @@ namespace BME_Utils {
void getWxModuleAddres() {
uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) {
#ifdef HELTEC_V3
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
Wire1.beginTransmission(addr);
err = Wire1.endTransmission();
#else
@@ -58,12 +58,12 @@ namespace BME_Utils {
if (wxModuleAddress != 0x00) {
bool wxModuleFound = false;
if (wxModuleAddress == 0x76 || wxModuleAddress == 0x77) {
#ifdef HELTEC_V3
if (bme280.begin(wxModuleAddress, &Wire1)) {
Serial.println("BME280 sensor found");
wxModuleType = 1;
wxModuleFound = true;
}
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
if (bme280.begin(wxModuleAddress, &Wire1)) {
Serial.println("BME280 sensor found");
wxModuleType = 1;
wxModuleFound = true;
}
#else
if (bme280.begin(wxModuleAddress)) {
Serial.println("BME280 sensor found");

View File

@@ -18,7 +18,7 @@
#define RADIO_BUSY_PIN 26 // GPIO26 - SX1278 IRQ ---->DIO0
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_WS)
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) || defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_WS)
#define RADIO_SCLK_PIN 9 // SX1262 SCK
#define RADIO_MISO_PIN 11 // SX1262 MISO
#define RADIO_MOSI_PIN 10 // SX1262 MOSI
@@ -40,6 +40,18 @@
#define RADIO_TXEN 25
#endif
#if defined(ESP32_DIY_1W_LoRa_Mesh_V1_2) // https://github.com/NanoVHF/Meshtastic-DIY/tree/main/PCB/ESP-32-devkit_EBYTE-E22/Mesh-v1.02-2LCD-FreePins
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#define RADIO_RXEN 14
#define RADIO_TXEN 13
#endif
#ifdef WEMOS_LOLIN32_OLED_DIY_LoRa
#define RADIO_SCLK_PIN 15
#define RADIO_MISO_PIN 13
@@ -122,7 +134,7 @@
// OLED
#if defined(TTGO_T_LORA32_V2_1) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) || defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262) || defined(OE5HWN_MeshCom) || defined(ESP32_DIY_LoRa_A7670) || defined(TTGO_T_LORA32_V2_1_915) || defined(ESP32_DIY_LoRa_915) || defined(TTGO_T_Beam_V1_0_915) || defined(TTGO_T_Beam_V1_2_915) || defined(ESP32_DIY_LoRa_A7670_915) || defined(ESP32_DIY_1W_LoRa_915)
#if defined(TTGO_T_LORA32_V2_1) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) || defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262) || defined(OE5HWN_MeshCom) || defined(ESP32_DIY_LoRa_A7670) || defined(TTGO_T_LORA32_V2_1_915) || defined(ESP32_DIY_LoRa_915) || defined(TTGO_T_Beam_V1_0_915) || defined(TTGO_T_Beam_V1_2_915) || defined(ESP32_DIY_LoRa_A7670_915) || defined(ESP32_DIY_1W_LoRa_915) || defined(ESP32_DIY_1W_LoRa_Mesh_V1_2)
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin)
@@ -147,7 +159,7 @@
#endif
#if !defined(HELTEC_HTCT62) && !defined(HELTEC_WSL_V3) && !defined(ESP32C3_DIY_1W_LoRa) && !defined(ESP32C3_DIY_1W_LoRa_915)
#define HAS_DISPLAY
#define HAS_DISPLAY
#endif
// Leds and other stuff
@@ -163,13 +175,16 @@
#define BATTERY_PIN 37
#define ADC_CTRL 21
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WS)
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) || defined(HELTEC_WS)
#define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 // Heltec WSL_V3 just like Heltec WT
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#ifdef HELTEC_WSL_V3_DISPLAY
#define OLED_RST -1
#endif
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_LoRa_915) || defined(ESP32_DIY_1W_LoRa) || defined(ESP32_DIY_1W_LoRa_915)
@@ -201,6 +216,19 @@
#define RADIO_IRQ_PIN 2
#endif
#if defined(ESP32_C3_OctopusLab_LoRa)
#define OLED_SDA 0
#define OLED_SCL 1
#define OLED_RST -1
#define RADIO_SCLK_PIN 6
#define RADIO_MISO_PIN 4
#define RADIO_MOSI_PIN 7
#define RADIO_CS_PIN 5
#define RADIO_DIO1_PIN 3
#define RADIO_RST_PIN -1
#define RADIO_BUSY_PIN 8
#endif
/* (Same pins for LILYGO LoRa32 and ESP32 Wroom Dev )
SX1278-------------------> ESP32 ttgo-lora32-v21 and ESP32 WROOM Dev
GND GND

View File

@@ -73,6 +73,9 @@ void Configuration::writeFile() {
data["battery"]["externalVoltagePin"] = battery.externalVoltagePin;
data["battery"]["monitorExternalVoltage"] = battery.monitorExternalVoltage;
data["battery"]["externalSleepVoltage"] = battery.externalSleepVoltage;
data["battery"]["voltageDividerR1"] = battery.voltageDividerR1;
data["battery"]["voltageDividerR2"] = battery.voltageDividerR2;
data["bme"]["active"] = bme.active;
data["bme"]["heightCorrection"] = bme.heightCorrection;
@@ -94,10 +97,16 @@ void Configuration::writeFile() {
data["other"]["rememberStationTime"] = rememberStationTime;
data["other"]["backupDigiMode"] = backupDigiMode;
data["other"]["backupDigiMode"] = backupDigiMode;
data["other"]["lowPowerMode"] = lowPowerMode;
data["other"]["lowVoltageCutOff"] = lowVoltageCutOff;
data["other"]["lowVoltageCutOff"] = lowVoltageCutOff;
data["personalNote"] = personalNote;
data["webadmin"]["active"] = webadmin.active;
data["webadmin"]["username"] = webadmin.username;
data["webadmin"]["password"] = webadmin.password;
serializeJson(data, configFile);
@@ -142,6 +151,8 @@ bool Configuration::readFile() {
battery.externalVoltagePin = data["battery"]["externalVoltagePin"].as<int>();
battery.monitorExternalVoltage = data["battery"]["monitorExternalVoltage"].as<bool>();
battery.externalSleepVoltage = data["battery"]["externalSleepVoltage"].as<float>();
battery.voltageDividerR1 = data["battery"]["voltageDividerR1"].as<float>();
battery.voltageDividerR2 = data["battery"]["voltageDividerR2"].as<float>();
aprs_is.passcode = data["aprs_is"]["passcode"].as<String>();
aprs_is.server = data["aprs_is"]["server"].as<String>();
@@ -179,6 +190,12 @@ bool Configuration::readFile() {
rebootMode = data["other"]["rebootMode"].as<bool>();
rebootModeTime = data["other"]["rebootModeTime"].as<int>();
personalNote = data["personalNote"].as<String>();
webadmin.active = data["webadmin"]["active"].as<bool>();
webadmin.username = data["webadmin"]["username"].as<String>();
webadmin.password = data["webadmin"]["password"].as<String>();
int stationMode = data["stationMode"].as<int>(); // deprecated but need to specify config version
if (stationMode == 0) {
@@ -330,7 +347,6 @@ void Configuration::init() {
ota.username = "";
ota.password = "";
rememberStationTime = 30;
battery.sendInternalVoltage = false;
@@ -341,6 +357,8 @@ void Configuration::init() {
battery.externalVoltagePin = 34;
battery.monitorExternalVoltage = false;
battery.externalSleepVoltage = 3.0;
battery.voltageDividerR1 = 100.0;
battery.voltageDividerR2 = 27.0;
lowPowerMode = false;
lowVoltageCutOff = 0;
@@ -350,6 +368,12 @@ void Configuration::init() {
rebootMode = false;
rebootModeTime = 0;
personalNote = "";
webadmin.active = false;
webadmin.username = "admin";
webadmin.password = "";
Serial.println("All is Written!");
}

View File

@@ -75,6 +75,8 @@ public:
int externalVoltagePin;
bool monitorExternalVoltage;
float externalSleepVoltage;
float voltageDividerR1;
float voltageDividerR2;
};
class BME {
@@ -104,6 +106,13 @@ public:
String password;
};
class WEBADMIN {
public:
bool active;
String username;
String password;
};
class Configuration {
public:
bool reload; // ?
@@ -114,6 +123,7 @@ public:
bool backupDigiMode;
bool rebootMode;
int rebootModeTime;
String personalNote;
std::vector<WiFi_AP> wifiAPs;
WiFi_Auto_AP wifiAutoAP;
BEACON beacon;
@@ -126,6 +136,7 @@ public:
SYSLOG syslog;
TNC tnc;
OTA ota;
WEBADMIN webadmin;
void init();
void writeFile();

View File

@@ -5,6 +5,7 @@
#include "query_utils.h"
#include "digi_utils.h"
#include "wifi_utils.h"
#include "lora_utils.h"
#include "gps_utils.h"
#include "display.h"
#include "utils.h"
@@ -27,7 +28,21 @@ namespace DIGI_Utils {
String buildPacket(const String& path, const String& packet, bool thirdParty) {
String packetToRepeat = packet.substring(0, packet.indexOf(",") + 1);
String tempPath = path;
tempPath.replace(Config.beacon.path, Config.callsign + "*");
if (path.indexOf("WIDE1-1") != -1 && (Config.digi.mode == 2 || Config.digi.mode == 3)) {
tempPath.replace("WIDE1-1", Config.callsign + "*");
} else if (path.indexOf("WIDE2-") != -1 && Config.digi.mode == 3) {
if (path.indexOf("*") != 1) {
tempPath.remove(path.indexOf("*"), 1);
}
if (path.indexOf("WIDE2-1") != -1) {
tempPath.replace("WIDE2-1", Config.callsign + "*");
} else if (path.indexOf("WIDE2-2") != -1) {
tempPath.replace("WIDE2-2", Config.callsign + "*,WIDE2-1");
} else {
return "";
}
}
packetToRepeat += tempPath;
if (thirdParty) {
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":}")));
@@ -47,8 +62,21 @@ namespace DIGI_Utils {
}
if (temp.indexOf(",") > 2) { // checks for path
const String& path = temp.substring(temp.indexOf(",") + 1); // after tocall
if (path.indexOf(Config.beacon.path) != -1) {
if ((Config.digi.mode == 2 || backUpDigiMode) && path.indexOf("WIDE1-1") != - 1) {
return buildPacket(path, packet, thirdParty);
} else if (Config.digi.mode == 3) {
int wide1Index = path.indexOf("WIDE1-1");
int wide2Index = path.indexOf("WIDE2-");
if (wide1Index != -1 && wide2Index != -1 && wide1Index < wide2Index) { // WIDE1-1 && WIDE2-n
return buildPacket(path, packet, thirdParty);
} else if (wide1Index != -1 && wide2Index == -1) { // only WIDE1-1
return buildPacket(path, packet, thirdParty);
} else if (wide1Index == -1 && wide2Index != -1) { // only WIDE2-n
return buildPacket(path, packet, thirdParty);
} else {
return "";
}
} else {
return "";
}
@@ -62,7 +90,8 @@ namespace DIGI_Utils {
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("NOGATE") == -1)) {
bool thirdPartyPacket = false;
String temp, Sender;
if (packet.indexOf("}") > 0 && packet.indexOf("TCPIP") > 0) { // 3rd Party
int firstColonIndex = packet.indexOf(":");
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] == '}' && packet.indexOf("TCPIP") > 0) { // 3rd Party
thirdPartyPacket = true;
temp = packet.substring(packet.indexOf(":}") + 2);
Sender = temp.substring(0, temp.indexOf(">"));
@@ -74,7 +103,7 @@ namespace DIGI_Utils {
if (!thirdPartyPacket && !Utils::checkValidCallsign(Sender)) {
return;
}
if (STATION_Utils::check25SegBuffer(Sender, temp.substring(temp.indexOf(":") + 2))) {
if (STATION_Utils::check25SegBuffer(Sender, temp.substring(temp.indexOf(":") + 2)) || Config.lowPowerMode) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(temp, 2); // Digi
bool queryMessage = false;
@@ -83,13 +112,17 @@ namespace DIGI_Utils {
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (Addressee == Config.callsign) { // it's a message for me!
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage);
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage, thirdPartyPacket);
}
}
if (!queryMessage) {
String loraPacket = generateDigiRepeatedPacket(packet.substring(3), thirdPartyPacket);
if (loraPacket != "") {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
if (Config.lowPowerMode) {
LoRa_Utils::sendNewPacket(loraPacket);
} else {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
}
display_toggle(true);
lastScreenOn = millis();
}

View File

@@ -11,9 +11,9 @@
TFT_eSPI tft = TFT_eSPI();
#ifdef HELTEC_WIRELESS_TRACKER
#define bigSizeFont 2
#define smallSizeFont 1
#define lineSpacing 9
#define bigSizeFont 2.5
#define smallSizeFont 1.5
#define lineSpacing 12
#endif
#else
#include <Adafruit_GFX.h>
@@ -21,7 +21,11 @@
#if defined(HELTEC_V3)
#define OLED_DISPLAY_HAS_RST_PIN
#endif
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RST);
#ifdef HELTEC_WSL_V3_DISPLAY
Adafruit_SSD1306 display(128, 64, &Wire1, OLED_RST);
#else
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RST);
#endif
#endif
#endif
@@ -55,7 +59,10 @@ void setup_display() {
delay(20);
digitalWrite(OLED_RST, HIGH);
#endif
Wire.begin(OLED_SDA, OLED_SCL);
#ifndef HELTEC_WSL_V3_DISPLAY
Wire.begin(OLED_SDA, OLED_SCL);
#endif
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));

View File

@@ -57,8 +57,12 @@ namespace GPS_Utils {
void generateBeacons() {
if (Config.callsign.indexOf("NOCALL-10") != 0 && !Utils::checkValidCallsign(Config.callsign)) {
show_display("***** ERROR ******", "CALLSIGN = NOT VALID!", " Use SSID 0-15", " Or Valid Callsign", 0);
while (true) {}
show_display("***** ERROR ******", "CALLSIGN = NOT VALID!", "", "Only Rx Mode Active", 3000);
Config.loramodule.txActive = false;
Config.aprs_is.messagesToRF = false;
Config.aprs_is.objectsToRF = false;
Config.beacon.sendViaRF = false;
Config.digi.mode = 0;
}
String beaconPacket = Config.callsign;
beaconPacket += ">APLRG1";

View File

@@ -43,11 +43,14 @@ namespace LoRa_Utils {
void setup() {
SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN);
float freq = (float)Config.loramodule.rxFreq / 1000000;
#if defined(RADIO_HAS_XTAL)
radio.XTAL = true;
#endif
int state = radio.begin(freq);
if (state == RADIOLIB_ERR_NONE) {
Utils::println("Initializing LoRa Module");
} else {
Utils::println("Starting LoRa failed!");
Utils::println("Starting LoRa failed! State: " + String(state));
while (true);
}
#if defined(HAS_SX1262) || defined(HAS_SX1268)
@@ -90,7 +93,7 @@ namespace LoRa_Utils {
if (state == RADIOLIB_ERR_NONE) {
Utils::println("init : LoRa Module ... done!");
} else {
Utils::println("Starting LoRa failed!");
Utils::println("Starting LoRa failed! State: " + String(state));
while (true);
}
}
@@ -157,9 +160,9 @@ namespace LoRa_Utils {
String receivePacket() {
String packet = "";
if (operationDone) {
if (operationDone || Config.lowPowerMode) {
operationDone = false;
if (transmitFlag) {
if (transmitFlag && !Config.lowPowerMode) {
radio.startReceive();
transmitFlag = false;
} else {

View File

@@ -164,7 +164,7 @@ namespace POWER_Utils {
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#ifdef HELTEC_V3
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif

View File

@@ -12,19 +12,21 @@ extern int freqError;
namespace QUERY_Utils {
String process(const String& query, const String& station, const uint8_t queryOrigin) {
String process(const String& query, const String& station, bool queryFromAPRSIS, bool thirdParty) {
String answer;
if (query=="?APRS?" || query=="?aprs?" || query=="?Aprs?" || query=="H" || query=="h" || query=="HELP" || query=="Help" || query=="help" || query=="?") {
String queryQuestion = query;
queryQuestion.toUpperCase();
if (queryQuestion == "?APRS?" || queryQuestion == "H" || queryQuestion == "HELP" || queryQuestion=="?") {
answer.concat("?APRSV ?APRSP ?APRSL ?APRSH ?WHERE callsign");
} else if (query=="?APRSV" || query=="?aprsv" || query=="?Aprsv") {
answer = "CA2RXU_LoRa_iGate 1.3 v";
} else if (queryQuestion == "?APRSV") {
answer.concat("CA2RXU_LoRa_iGate 1.4 v");
answer.concat(versionDate);
} else if (query=="?APRSP" || query=="?aprsp" || query=="?Aprsp") {
answer = "iGate QTH: ";
answer.concat(String(Config.beacon.latitude,2));
} else if (queryQuestion == "?APRSP") {
answer.concat("iGate QTH: ");
answer.concat(String(Config.beacon.latitude,3));
answer.concat(" ");
answer.concat(String(Config.beacon.longitude,2));
} else if (query=="?APRSL" || query=="?aprsl" || query=="?Aprsl") {
answer.concat(String(Config.beacon.longitude,3));
} else if (queryQuestion == "?APRSL") {
if (lastHeardStation.size() == 0) {
char answerArray[50];
snprintf(answerArray, sizeof(answerArray), "No Station Listened in the last %d min.", Config.rememberStationTime);
@@ -35,36 +37,37 @@ namespace QUERY_Utils {
}
answer.trim();
}
} else if (query=="?APRSSR" || query=="?aprssr" || query=="?Aprssr") {
} else if (queryQuestion == "?APRSSR") {
char signalData[35];
snprintf(signalData, sizeof(signalData), " %ddBm / %.2fdB / %dHz", rssi, snr, freqError);
answer.concat(signalData);
} else if (query.indexOf("?APRSH") == 0 || query.indexOf("?aprsh") == 0 || query.indexOf("?Aprsh") == 0) {
} else if (queryQuestion.indexOf("?APRSH") == 0) {
// sacar callsign despues de ?APRSH
Serial.println("escuchaste a X estacion? en las ultimas 24 o 8 horas?");
answer.concat("?APRSH on development 73!");
} else if (query.indexOf("?WHERE") == 0) {
} else if (queryQuestion.indexOf("?WHERE") == 0) {
// agregar callsign para completar donde esta X callsign --> posicion
Serial.println("estaciones escuchadas directo (ultimos 30 min)");
answer.concat("?WHERE on development 73!");
}
String queryAnswer = Config.callsign;
queryAnswer += ">APLRG1";
if (queryFromAPRSIS) {
queryAnswer += ",TCPIP,qAC";
} else {
if (!thirdParty) queryAnswer += ",RFONLY";
if (Config.beacon.path != "") {
queryAnswer += ",";
queryAnswer += Config.beacon.path;
}
}
queryAnswer += "::";
String processedStation = station;
for (int i = station.length(); i < 9; i++) {
processedStation += ' ';
}
String queryAnswer = Config.callsign;
queryAnswer += ">APLRG1,";
if (queryOrigin == 1) { // from APRS-IS
queryAnswer += "TCPIP,qAC::";
} else { // else == 0 , from LoRa
if (Config.beacon.path == "") {
queryAnswer += "RFONLY::";
} else {
queryAnswer += "RFONLY,";
queryAnswer += Config.beacon.path;
queryAnswer += "::";
}
}
queryAnswer += processedStation;
queryAnswer += ":";
queryAnswer += answer;

View File

@@ -6,7 +6,7 @@
namespace QUERY_Utils {
String process(const String& query, const String& station, const uint8_t queryOrigin);
String process(const String& query, const String& station, bool queryFromAPRSIS, bool thirdParty);
}

View File

@@ -237,13 +237,14 @@ namespace Utils {
seventhLineHelper += String(snr);
seventhLineHelper += "dBm";
if (packet.indexOf("::") >= 10) {
int firstColonIndex = packet.indexOf(":");
if (packet[firstColonIndex + 1] == ':') {
sixthLine += "> MESSAGE";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":>") >= 10) {
} else if (packet[firstColonIndex + 1] == '>') {
sixthLine += "> NEW STATUS";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":!") >= 10 || packet.indexOf(":=") >= 10) {
} else if (packet[firstColonIndex + 1] == '!' || packet[firstColonIndex + 1] == '=') {
sixthLine += "> GPS BEACON";
if (!Config.syslog.active) {
GPS_Utils::getDistanceAndComment(packet); // to be checked!!!
@@ -262,15 +263,15 @@ namespace Utils {
seventhLine += "D:";
seventhLine += distance;
seventhLine += "km";
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) {
sixthLine += "> TELEMETRY";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":`") >= 10) {
} else if (packet[firstColonIndex + 1] == '`' || packet[firstColonIndex + 1] == '\'') {
sixthLine += "> MIC-E";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":;") >= 10) {
} else if (packet[firstColonIndex + 1] == ';') {
sixthLine += "> OBJECT";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) {
sixthLine += "> TELEMETRY";
seventhLine = seventhLineHelper;
} else {
sixthLine += "> ??????????";
seventhLine = seventhLineHelper;
@@ -330,7 +331,7 @@ namespace Utils {
if (callsign == "WLNK-1") return true;
String cleanCallsign;
if (callsign.indexOf("-")) { // SSID Validation
if (callsign.indexOf("-") > 0) { // SSID Validation
cleanCallsign = callsign.substring(0, callsign.indexOf("-"));
String ssid = callsign.substring(callsign.indexOf("-") + 1);
if (ssid.indexOf("-") != -1 || ssid.length() > 2) return false;
@@ -347,22 +348,25 @@ namespace Utils {
cleanCallsign = " " + cleanCallsign; // A0AA --> _A0AA
}
if (!isDigit(cleanCallsign[2]) || !isAlpha(cleanCallsign[3])) return false; // __0A must be validated
if (!isDigit(cleanCallsign[2]) || !isAlpha(cleanCallsign[3])) { // __0A__ must be validated
if (cleanCallsign[0] != 'R' && !isDigit(cleanCallsign[1]) && !isAlpha(cleanCallsign[2])) return false; // to accepto R0A___
}
bool isValid = false;
if ((isAlphaNumeric(cleanCallsign[0]) || cleanCallsign[0] == ' ') && isAlpha(cleanCallsign[1])) {
isValid = true; // AA0A (+A+A) + _A0AA (+A) + 0A0A (+A+A)
} else if (isAlpha(cleanCallsign[0]) && isDigit(cleanCallsign[1])) {
isValid = true; // A00A (+A+A)
} else if (cleanCallsign[0] == 'R' && cleanCallsign.length() == 6 && isDigit(cleanCallsign[1]) && isAlpha(cleanCallsign[2]) && isAlpha(cleanCallsign[3]) && isAlpha(cleanCallsign[4])) {
isValid = true; // R0AA (+A+A)
}
if (!isValid) return false; // also 00__ avoided
if (cleanCallsign.length() > 4) {
if (cleanCallsign.length() > 4) { // to validate ____AA
for (int i = 5; i <= cleanCallsign.length(); i++) {
if (!isAlpha(cleanCallsign[i - 1])) return false;
}
}
return true;
}

View File

@@ -29,6 +29,10 @@ extern const char web_bootstrap_js[] asm("_binary_data_embed_bootstrap_js_gz_sta
extern const char web_bootstrap_js_end[] asm("_binary_data_embed_bootstrap_js_gz_end");
extern const size_t web_bootstrap_js_len = web_bootstrap_js_end - web_bootstrap_js;
// Declare external symbols for the embedded image data
extern const unsigned char favicon_data[] asm("_binary_data_embed_favicon_png_gz_start");
extern const unsigned char favicon_data_end[] asm("_binary_data_embed_favicon_png_gz_end");
extern const size_t favicon_data_len = favicon_data_end - favicon_data;
namespace WEB_Utils {
@@ -45,12 +49,24 @@ namespace WEB_Utils {
}
void handleHome(AsyncWebServerRequest *request) {
if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str()))
return request->requestAuthentication();
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", (const uint8_t*)web_index_html, web_index_html_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
void handleFavicon(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "image/x-icon", (const uint8_t*)favicon_data, favicon_data_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
void handleReadConfiguration(AsyncWebServerRequest *request) {
if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str()))
return request->requestAuthentication();
File file = SPIFFS.open("/igate_conf.json");
String fileContent;
@@ -141,16 +157,17 @@ namespace WEB_Utils {
Config.battery.sendInternalVoltage = request->hasParam("battery.sendInternalVoltage", true);
Config.battery.monitorInternalVoltage = request->hasParam("battery.monitorInternalVoltage", true);
Config.battery.internalSleepVoltage = request->getParam("battery.internalSleepVoltage", true)->value().toFloat();
Config.battery.internalSleepVoltage = request->getParam("battery.internalSleepVoltage", true)->value().toFloat();
Config.battery.sendExternalVoltage = request->hasParam("battery.sendExternalVoltage", true);
if (Config.battery.sendExternalVoltage) {
Config.battery.externalVoltagePin = request->getParam("battery.externalVoltagePin", true)->value().toInt();
Config.battery.voltageDividerR1 = request->getParam("battery.voltageDividerR1", true)->value().toFloat();
Config.battery.voltageDividerR2 = request->getParam("battery.voltageDividerR2", true)->value().toFloat();
}
Config.battery.monitorExternalVoltage = request->hasParam("battery.monitorExternalVoltage", true);
Config.battery.externalSleepVoltage = request->getParam("battery.externalSleepVoltage", true)->value().toFloat();
Config.battery.externalSleepVoltage = request->getParam("battery.externalSleepVoltage", true)->value().toFloat();
Config.bme.active = request->hasParam("bme.active", true);
Config.bme.heightCorrection = request->getParam("bme.heightCorrection", true)->value().toInt();
Config.bme.temperatureCorrection = request->getParam("bme.temperatureCorrection", true)->value().toFloat();
@@ -158,36 +175,36 @@ namespace WEB_Utils {
Config.beacon.symbol = "_";
}
Config.syslog.active = request->hasParam("syslog.active", true);
if (Config.syslog.active) {
Config.syslog.server = request->getParam("syslog.server", true)->value();
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt();
Config.syslog.server = request->getParam("syslog.server", true)->value();
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt();
}
Config.tnc.enableServer = request->hasParam("tnc.enableServer", true);
Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true);
Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true);
Config.tnc.enableServer = request->hasParam("tnc.enableServer", true);
Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true);
Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true);
Config.rebootMode = request->hasParam("other.rebootMode", true);
Config.rebootModeTime = request->getParam("other.rebootModeTime", true)->value().toInt();
Config.ota.username = request->getParam("ota.username", true)->value();
Config.ota.password = request->getParam("ota.password", true)->value();
Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt();
Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt();
Config.backupDigiMode = request->hasParam("other.backupDigiMode", true);
Config.lowPowerMode = request->hasParam("other.lowPowerMode", true);
Config.lowVoltageCutOff = request->getParam("other.lowVoltageCutOff", true)->value().toDouble();
Config.personalNote = request->getParam("personalNote", true)->value();
Config.webadmin.active = request->hasParam("webadmin.active", true);
if (Config.webadmin.active) {
Config.webadmin.username = request->getParam("webadmin.username", true)->value();
Config.webadmin.password = request->getParam("webadmin.password", true)->value();
}
Config.writeFile();
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
@@ -249,6 +266,7 @@ namespace WEB_Utils {
server.on("/script.js", HTTP_GET, handleScript);
server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle);
server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript);
server.on("/favicon.png", HTTP_GET, handleFavicon);
OTA_Utils::setup(&server); // Include OTA Updater for WebServer

View File

@@ -40,7 +40,7 @@ namespace WIFI_Utils {
Serial.print(millis());
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
WIFI_Utils::startWiFi();//WiFi.reconnect();
previousWiFiMillis = millis();
if (Config.backupDigiMode) {
@@ -110,7 +110,9 @@ namespace WIFI_Utils {
#endif
if (WiFi.status() == WL_CONNECTED) {
Serial.print("Connected as ");
Serial.println(WiFi.localIP());
Serial.print(WiFi.localIP());
Serial.print(" / MAC Address: ");
Serial.println(WiFi.macAddress());
show_display("", " Connected!!", "" , " loading ...", 1000);
} else if (WiFi.status() != WL_CONNECTED) {
startAP = true;

View File

@@ -9,8 +9,21 @@ files = [
'data_embed/style.css',
'data_embed/bootstrap.js',
'data_embed/bootstrap.css',
'data_embed/favicon.png',
]
string_to_find_str = "String"
string_to_find_ver = "versionDate"
with open('src/LoRa_APRS_iGate.cpp', encoding='utf-8') as cpp_file:
for line in cpp_file:
if string_to_find_str in line and string_to_find_ver in line:
start = line.find('"') + 1
end = line.find('"', start)
if start > 0 and end > start:
versionDate = line[start:end]
break
for src in files:
out = src + ".gz"
@@ -19,7 +32,7 @@ for src in files:
content = f.read()
if src == 'data_embed/index.html':
env_vars = env["BOARD"] + "<br>" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '')
env_vars = env["BOARD"] + "<br>" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '') + "<br>" + "Version date: " + versionDate
current_date = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') + " UTC"
build_info = f'{env_vars}<br>Build date: {current_date}'.encode()