Compare commits

...

14 Commits

Author SHA1 Message Date
Ricardo Guzman (Richonguzman) bf6a0faa90 killing blank spaces 2026-02-24 23:33:58 -03:00
Ricardo Guzman (Richonguzman) 61cf118a3b cleaning Headers 2026-02-24 23:27:36 -03:00
Ricardo Guzman (Richonguzman) 44719083a6 new callsignIsValid update 2026-02-24 21:26:20 -03:00
Ricardo Guzman (Richonguzman) 808d740477 update indexOf kill 2026-02-24 19:29:20 -03:00
Ricardo Guzman (Richonguzman) 23c8257c80 date update 2026-02-24 07:55:53 -03:00
Ricardo Guzman (Richonguzman) db4582db13 telemetry EUP beacon update 2026-02-24 07:55:32 -03:00
Ricardo Guzman (Richonguzman) 09e06d36e8 checkCallsignList update 2026-02-24 06:50:27 -03:00
Ricardo Guzman (Richonguzman) e6d44c1b7f replaced string for hash in 25segBuffer 2026-02-23 18:59:27 -03:00
Ricardo Guzman (Richonguzman) d4fc99466f update digi2000 2026-02-23 18:07:26 -03:00
Ricardo Guzman (Richonguzman) 41f09af7b5 digipeater logic improved 2026-02-23 17:32:52 -03:00
Ricardo Guzman (Richonguzman) 0eec028c5d update SENSOR BUS 2026-02-23 12:00:55 -03:00
Ricardo Guzman (Richonguzman) c48dd15bd6 better ADC and VEXT control 2026-02-23 11:14:42 -03:00
Ricardo Guzman (Richonguzman) f26ded5b5c less memory fixes too 2026-02-20 17:36:26 -03:00
Ricardo Guzman (Richonguzman) c887689406 indexOf transformation 2026-02-20 17:03:39 -03:00
62 changed files with 631 additions and 597 deletions
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+9 -9
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -44,7 +44,7 @@ public:
int interval; int interval;
String overlay; String overlay;
String symbol; String symbol;
String path; String path;
bool sendViaAPRSIS; bool sendViaAPRSIS;
bool sendViaRF; bool sendViaRF;
int beaconFreq; int beaconFreq;
@@ -78,7 +78,7 @@ public:
long rxFreq; long rxFreq;
int rxSpreadingFactor; int rxSpreadingFactor;
int rxCodingRate4; int rxCodingRate4;
long rxSignalBandwidth; long rxSignalBandwidth;
bool txActive; bool txActive;
long txFreq; long txFreq;
int txSpreadingFactor; int txSpreadingFactor;
@@ -188,10 +188,10 @@ public:
BATTERY battery; BATTERY battery;
WXSENSOR wxsensor; WXSENSOR wxsensor;
SYSLOG syslog; SYSLOG syslog;
TNC tnc; TNC tnc;
OTA ota; OTA ota;
WEBADMIN webadmin; WEBADMIN webadmin;
NTP ntp; NTP ntp;
REMOTE_MANAGEMENT remoteManagement; REMOTE_MANAGEMENT remoteManagement;
MQTT mqtt; MQTT mqtt;
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+6 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -21,6 +21,7 @@
#include <Arduino.h> #include <Arduino.h>
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 #define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
void displaySetup(); void displaySetup();
+6 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -23,7 +23,7 @@
namespace GPS_Utils { namespace GPS_Utils {
String getiGateLoRaBeaconPacket(); String getiGateLoRaBeaconPacket();
char *ax25_base91enc(char *s, uint8_t n, uint32_t v); char *ax25_base91enc(char *s, uint8_t n, uint32_t v);
String encodeGPS(float latitude, float longitude, const String& overlay, const String& symbol); String encodeGPS(float latitude, float longitude, const String& overlay, const String& symbol);
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+7 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -21,8 +21,9 @@
#include <Arduino.h> #include <Arduino.h>
namespace SLEEP_Utils { namespace SLEEP_Utils {
void setup(); void setup();
void checkWakeUpFlag(); void checkWakeUpFlag();
void startSleeping(); void startSleeping();
+6 -7
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -37,8 +37,7 @@ namespace STATION_Utils {
void deleteNotHeard(); void deleteNotHeard();
void updateLastHeard(const String& station); void updateLastHeard(const String& station);
bool wasHeard(const String& station); bool wasHeard(const String& station);
void clean25SegBuffer(); bool isIn25SegHashBuffer(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, bool flag = false); void addToOutputPacketBuffer(const String& packet, bool flag = false);
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+7 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -27,7 +27,8 @@ namespace TELEMETRY_Utils {
void sendEquationsUnitsParameters(); void sendEquationsUnitsParameters();
String generateEncodedTelemetryBytes(float value, bool counterBytes, byte telemetryType); String generateEncodedTelemetryBytes(float value, bool counterBytes, byte telemetryType);
String generateEncodedTelemetry(); String generateEncodedTelemetry();
void checkEUPInterval();
} }
#endif #endif
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+6 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -20,7 +20,7 @@
#define WX_UTILS_H_ #define WX_UTILS_H_
#include <Adafruit_Sensor.h> #include <Adafruit_Sensor.h>
#include <Adafruit_AHTX0.h> #include <Adafruit_AHTX0.h>
#include <Adafruit_BME280.h> #include <Adafruit_BME280.h>
#include <Adafruit_BMP280.h> #include <Adafruit_BMP280.h>
#include <Adafruit_BME680.h> #include <Adafruit_BME680.h>
+14 -12
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -26,7 +26,7 @@
#ifdef HAS_A7670 #ifdef HAS_A7670
#define TINY_GSM_MODEM_SIM7600 //The AT instruction of A7670 is compatible with SIM7600 #define TINY_GSM_MODEM_SIM7600 //The AT instruction of A7670 is compatible with SIM7600
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb #define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#define SerialAT Serial1 #define SerialAT Serial1
#include <TinyGsmClient.h> #include <TinyGsmClient.h>
@@ -115,6 +115,8 @@
if (SerialAT.available()) { if (SerialAT.available()) {
String response = SerialAT.readString(); String response = SerialAT.readString();
//Serial.println(response); // DEBUG of Modem AT message //Serial.println(response); // DEBUG of Modem AT message
int responseOKIndex = response.indexOf("OK");
int callsignIndex = ATMessage.indexOf(Config.callsign);
if(response.indexOf("verified") >= 0) { if(response.indexOf("verified") >= 0) {
Serial.println("Logged! (User Validated)\n"); Serial.println("Logged! (User Validated)\n");
displayShow(firstLine, "Connecting APRS-IS...", "---> Logged!", " ", 1000); displayShow(firstLine, "Connecting APRS-IS...", "---> Logged!", " ", 1000);
@@ -122,7 +124,7 @@
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
} else if (ATMessage == "AT+NETOPEN" && response.indexOf("OK") >= 0) { } else if (ATMessage == "AT+NETOPEN" && responseOKIndex >= 0) {
Serial.println("Port Open!"); Serial.println("Port Open!");
displayShow(firstLine, "Opening Port...", "---> Port Open", " ", 0); displayShow(firstLine, "Opening Port...", "---> Port Open", " ", 0);
validAT = true; validAT = true;
@@ -145,14 +147,14 @@
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
} else if (ATMessage.indexOf(Config.callsign) >= 3 && !modemLoggedToAPRSIS && response.indexOf("OK") >= 0 && !stationBeacon) { // login info } else if (callsignIndex >= 3 && !modemLoggedToAPRSIS && responseOKIndex >= 0 && !stationBeacon) { // login info
validAT = true; validAT = true;
delayATMessage = 0; delayATMessage = 0;
} else if (ATMessage.indexOf(Config.callsign) == 0 && !beaconSent && response.indexOf("OK") >= 0 && !stationBeacon) { // self beacon or querys } else if (callsignIndex == 0 && !beaconSent && responseOKIndex >= 0 && !stationBeacon) { // self beacon or querys
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
} else if (stationBeacon && response.indexOf("OK") >= 0) { //upload others beacons } else if (stationBeacon && responseOKIndex >= 0) { //upload others beacons
validAT = true; validAT = true;
i = 1; i = 1;
delayATMessage = 0; delayATMessage = 0;
@@ -200,7 +202,7 @@
if (beaconBytesSent) { if (beaconBytesSent) {
Serial.print("."); Serial.print(".");
beaconSent = checkATResponse(packet); beaconSent = checkATResponse(packet);
} }
if (!beaconSent) { if (!beaconSent) {
Serial.println("------------------------------------> UPLOAD FAILED!!!"); Serial.println("------------------------------------> UPLOAD FAILED!!!");
} else { } else {
@@ -221,5 +223,5 @@
delay(1); delay(1);
} }
} }
#endif #endif
+9 -10
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -24,7 +24,7 @@
██║ ██║ ██║██╔══██╗██╔══██║ ██╔══██║██╔═══╝ ██╔══██╗╚════██║ ██║ ██║ ██║██╔══██╗██╔══██║ ██╔══██║██╔═══╝ ██╔══██╗╚════██║
███████╗╚██████╔╝██║ ██║██║ ██║ ██║ ██║██║ ██║ ██║███████║ ███████╗╚██████╔╝██║ ██║██║ ██║ ██║ ██║██║ ██║ ██║███████║
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝
██╗ ██████╗ █████╗ ████████╗███████╗ ██╗ ██████╗ █████╗ ████████╗███████╗
██║██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝ ██║██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝
██║██║ ███╗███████║ ██║ █████╗ ██║██║ ███╗███████║ ██║ █████╗
@@ -67,7 +67,7 @@ ___________________________________________________________________*/
#endif #endif
String versionDate = "2026-02-16"; String versionDate = "2026-02-24";
String versionNumber = "3.2"; String versionNumber = "3.2";
Configuration Config; Configuration Config;
WiFiClient aprsIsClient; WiFiClient aprsIsClient;
@@ -138,7 +138,7 @@ void loop() {
ElegantOTA.loop(); ElegantOTA.loop();
return; // Don't process IGate and Digi during OTA update return; // Don't process IGate and Digi during OTA update
} }
#ifdef HAS_GPS #ifdef HAS_GPS
if (Config.beacon.gpsActive) { if (Config.beacon.gpsActive) {
if (millis() - gpsSatelliteTime > 5000) { if (millis() - gpsSatelliteTime > 5000) {
@@ -174,7 +174,7 @@ void loop() {
Utils::checkDisplayInterval(); Utils::checkDisplayInterval();
Utils::checkBeaconInterval(); Utils::checkBeaconInterval();
APRS_IS_Utils::checkStatus(); // Need that to update display, maybe split this and send APRSIS status to display func? APRS_IS_Utils::checkStatus(); // Need that to update display, maybe split this and send APRSIS status to display func?
String packet = ""; String packet = "";
@@ -188,7 +188,6 @@ void loop() {
} }
if (Config.loramodule.txActive && (Config.digi.mode == 2 || Config.digi.mode == 3 || backupDigiMode)) { // If Digi enabled if (Config.loramodule.txActive && (Config.digi.mode == 2 || Config.digi.mode == 3 || backupDigiMode)) { // If Digi enabled
STATION_Utils::clean25SegBuffer();
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
} }
+48 -40
View File
@@ -135,30 +135,30 @@ namespace APRS_IS_Utils {
} }
String checkForStartingBytes(const String& packet) { String checkForStartingBytes(const String& packet) {
if (packet.indexOf("\x3c\xff\x01") != -1) { int index = packet.indexOf("\x3c\xff\x01");
return packet.substring(0, packet.indexOf("\x3c\xff\x01")); return (index != -1) ? packet.substring(0, index) : packet;
} else {
return packet;
}
} }
String buildPacketToUpload(const String& packet) { String buildPacketToUpload(const String& packet) {
String packetToUpload = packet.substring(3, packet.indexOf(":")); int colonIndex = packet.indexOf(":");
String packetToUpload = packet.substring(3, colonIndex);
if (Config.aprs_is.active && passcodeValid && Config.aprs_is.messagesToRF) { if (Config.aprs_is.active && passcodeValid && Config.aprs_is.messagesToRF) {
packetToUpload += ",qAR,"; packetToUpload += ",qAR,";
} else { } else {
packetToUpload += ",qAO,"; packetToUpload += ",qAO,";
} }
packetToUpload += Config.callsign; packetToUpload += Config.callsign;
packetToUpload += checkForStartingBytes(packet.substring(packet.indexOf(":"))); packetToUpload += checkForStartingBytes(packet.substring(colonIndex));
return packetToUpload; return packetToUpload;
} }
bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty) { bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty) {
String receivedMessage; String receivedMessage;
if (packet.indexOf("{") > 0) { // ack? int leftCurlyBraceIndex = packet.indexOf("{");
int colonIndex = packet.indexOf(":");
if (leftCurlyBraceIndex > 0) { // ack?
String ackMessage = "ack"; String ackMessage = "ack";
ackMessage.concat(packet.substring(packet.indexOf("{") + 1)); ackMessage.concat(packet.substring(leftCurlyBraceIndex + 1));
ackMessage.trim(); ackMessage.trim();
//Serial.println(ackMessage); //Serial.println(ackMessage);
@@ -180,9 +180,9 @@ namespace APRS_IS_Utils {
addToBuffer += ":"; addToBuffer += ":";
addToBuffer += ackMessage; addToBuffer += ackMessage;
STATION_Utils::addToOutputPacketBuffer(addToBuffer); STATION_Utils::addToOutputPacketBuffer(addToBuffer);
receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{")); receivedMessage = packet.substring(colonIndex + 1, leftCurlyBraceIndex);
} else { } else {
receivedMessage = packet.substring(packet.indexOf(":") + 1); receivedMessage = packet.substring(colonIndex + 1);
} }
if (receivedMessage.indexOf("?") == 0) { if (receivedMessage.indexOf("?") == 0) {
if (!Config.display.alwaysOn && Config.display.timeout != 0) { if (!Config.display.alwaysOn && Config.display.timeout != 0) {
@@ -207,29 +207,30 @@ namespace APRS_IS_Utils {
if (Sender != Config.callsign && Utils::callsignIsValid(Sender)) { if (Sender != Config.callsign && Utils::callsignIsValid(Sender)) {
STATION_Utils::updateLastHeard(Sender); STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2); int doubleColonIndex = packet.indexOf("::");
const String& AddresseeAndMessage = packet.substring(doubleColonIndex + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim(); Addressee.trim();
bool queryMessage = false; bool queryMessage = false;
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me! if (doubleColonIndex > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage), false); queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage), false);
} }
if (!queryMessage) { if (queryMessage) return;
const String& aprsPacket = buildPacketToUpload(packet);
if (!Config.display.alwaysOn && Config.display.timeout != 0) { const String& aprsPacket = buildPacketToUpload(packet);
displayToggle(true); if (!Config.display.alwaysOn && Config.display.timeout != 0) {
} displayToggle(true);
lastScreenOn = millis();
#ifdef HAS_A7670
stationBeacon = true;
A7670_Utils::uploadToAPRSIS(aprsPacket);
stationBeacon = false;
#else
upload(aprsPacket);
#endif
Utils::println("---> Uploaded to APRS-IS");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
} }
lastScreenOn = millis();
#ifdef HAS_A7670
stationBeacon = true;
A7670_Utils::uploadToAPRSIS(aprsPacket);
stationBeacon = false;
#else
upload(aprsPacket);
#endif
Utils::println("---> Uploaded to APRS-IS");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
} }
} }
} }
@@ -245,26 +246,30 @@ namespace APRS_IS_Utils {
outputPacket.concat(",TCPIP,"); outputPacket.concat(",TCPIP,");
outputPacket.concat(Config.callsign); outputPacket.concat(Config.callsign);
outputPacket.concat("*"); outputPacket.concat("*");
int colonEqualIndex = packet.indexOf(":=");
int doubleColonIndex = packet.indexOf("::");
int colonInvAccentIndex = packet.indexOf(":`");
switch (packetType) { switch (packetType) {
case 0: // gps case 0: // gps
if (packet.indexOf(":=") > 0) { if (colonEqualIndex > 0) {
outputPacket += packet.substring(packet.indexOf(":=")); outputPacket += packet.substring(colonEqualIndex);
} else { } else {
outputPacket += packet.substring(packet.indexOf(":!")); outputPacket += packet.substring(packet.indexOf(":!"));
} }
break; break;
case 1: // messages case 1: // messages
outputPacket += packet.substring(packet.indexOf("::")); outputPacket += packet.substring(doubleColonIndex);
break; break;
case 2: // status case 2: // status
outputPacket += packet.substring(packet.indexOf(":>")); outputPacket += packet.substring(packet.indexOf(":>"));
break; break;
case 3: // telemetry case 3: // telemetry
outputPacket += packet.substring(packet.indexOf("::")); outputPacket += packet.substring(doubleColonIndex);
break; break;
case 4: // mic-e case 4: // mic-e
if (packet.indexOf(":`") > 0) { if (colonInvAccentIndex > 0) {
outputPacket += packet.substring(packet.indexOf(":`")); outputPacket += packet.substring(colonInvAccentIndex);
} else { } else {
outputPacket += packet.substring(packet.indexOf(":'")); outputPacket += packet.substring(packet.indexOf(":'"));
} }
@@ -316,18 +321,21 @@ namespace APRS_IS_Utils {
if (packet.startsWith("#")) { if (packet.startsWith("#")) {
if (Config.digi.backupDigiMode) lastServerCheck = currentTime; if (Config.digi.backupDigiMode) lastServerCheck = currentTime;
} else { } else {
if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) { int doubleColonIndex = packet.indexOf("::");
if (Config.aprs_is.messagesToRF && doubleColonIndex > 0) {
String Sender = packet.substring(0, packet.indexOf(">")); String Sender = packet.substring(0, packet.indexOf(">"));
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2); const String& AddresseeAndMessage = packet.substring(doubleColonIndex + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); int colonIndex = AddresseeAndMessage.indexOf(":");
String Addressee = AddresseeAndMessage.substring(0, colonIndex);
Addressee.trim(); Addressee.trim();
if (Addressee == Config.callsign) { // its for me! if (Addressee == Config.callsign) { // its for me!
String receivedMessage; String receivedMessage;
if (AddresseeAndMessage.indexOf("{") > 0) { // ack? int curlyBraceIndex = AddresseeAndMessage.indexOf("{");
if (curlyBraceIndex > 0) { // ack?
processAckMessage(Sender, AddresseeAndMessage); processAckMessage(Sender, AddresseeAndMessage);
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1, AddresseeAndMessage.indexOf("{")); receivedMessage = AddresseeAndMessage.substring(colonIndex + 1, curlyBraceIndex);
} else { } else {
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1); receivedMessage = AddresseeAndMessage.substring(colonIndex + 1);
} }
if (receivedMessage.indexOf("?") == 0) { if (receivedMessage.indexOf("?") == 0) {
Utils::println("Rx Query (APRS-IS) : " + packet); Utils::println("Rx Query (APRS-IS) : " + packet);
+12 -12
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -105,9 +105,9 @@ namespace BATTERY_Utils {
void getI2CVoltageSensorAddress() { void getI2CVoltageSensorAddress() {
uint8_t err, addr; uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) { for(addr = 1; addr < 0x7F; addr++) {
#if defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) #ifdef SENSOR_I2C_BUS
Wire1.beginTransmission(addr); SENSOR_I2C_BUS.beginTransmission(addr);
err = Wire1.endTransmission(); err = SENSOR_I2C_BUS.endTransmission();
#else #else
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
err = Wire.endTransmission(); err = Wire.endTransmission();
@@ -145,7 +145,7 @@ namespace BATTERY_Utils {
} }
} }
float checkInternalVoltage() { float checkInternalVoltage() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101) #if defined(HAS_AXP192) || defined(HAS_AXP2101)
if(POWER_Utils::isBatteryConnected()) { if(POWER_Utils::isBatteryConnected()) {
return POWER_Utils::getBatteryVoltage(); return POWER_Utils::getBatteryVoltage();
@@ -153,7 +153,7 @@ namespace BATTERY_Utils {
return 0.0; return 0.0;
} }
#else #else
#ifdef ADC_CTRL #ifdef ADC_CTRL
POWER_Utils::adc_ctrl_ON(); POWER_Utils::adc_ctrl_ON();
#endif #endif
@@ -177,7 +177,7 @@ namespace BATTERY_Utils {
#endif #endif
#endif #endif
#endif #endif
delay(3); delay(3);
} }
#ifdef ADC_CTRL #ifdef ADC_CTRL
@@ -241,7 +241,7 @@ namespace BATTERY_Utils {
#else #else
extVoltage = ((((sampleSum/100.0)* adcReadingTransformation) + readingCorrection) * voltageDividerTransformation) - multiplyCorrection; extVoltage = ((((sampleSum/100.0)* adcReadingTransformation) + readingCorrection) * voltageDividerTransformation) - multiplyCorrection;
#endif #endif
return extVoltage; // raw voltage without mapping return extVoltage; // raw voltage without mapping
// return mapVoltage(voltage, 5.05, 6.32, 4.5, 5.5); // mapped voltage // return mapVoltage(voltage, 5.05, 6.32, 4.5, 5.5); // mapped voltage
+19 -19
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -96,12 +96,12 @@ bool Configuration::writeFile() {
data["lora"]["rxFreq"] = loramodule.rxFreq; data["lora"]["rxFreq"] = loramodule.rxFreq;
data["lora"]["rxCodingRate4"] = loramodule.rxCodingRate4; data["lora"]["rxCodingRate4"] = loramodule.rxCodingRate4;
data["lora"]["rxSignalBandwidth"] = loramodule.rxSignalBandwidth; data["lora"]["rxSignalBandwidth"] = loramodule.rxSignalBandwidth;
data["lora"]["txActive"] = loramodule.txActive; data["lora"]["txActive"] = loramodule.txActive;
data["lora"]["txFreq"] = loramodule.txFreq; data["lora"]["txFreq"] = loramodule.txFreq;
data["lora"]["txCodingRate4"] = loramodule.txCodingRate4; data["lora"]["txCodingRate4"] = loramodule.txCodingRate4;
data["lora"]["txSignalBandwidth"] = loramodule.txSignalBandwidth; data["lora"]["txSignalBandwidth"] = loramodule.txSignalBandwidth;
data["lora"]["power"] = loramodule.power; data["lora"]["power"] = loramodule.power;
int rxSpreadingFactor = loramodule.rxSpreadingFactor; int rxSpreadingFactor = loramodule.rxSpreadingFactor;
int txSpreadingFactor = loramodule.txSpreadingFactor; int txSpreadingFactor = loramodule.txSpreadingFactor;
#if defined(HAS_SX1276) || defined(HAS_SX1278) #if defined(HAS_SX1276) || defined(HAS_SX1278)
@@ -222,7 +222,7 @@ bool Configuration::readFile() {
callsign = data["callsign"] | "NOCALL-10"; callsign = data["callsign"] | "NOCALL-10";
if (!data.containsKey("tacticalCallsign")) needsRewrite = true; if (!data.containsKey("tacticalCallsign")) needsRewrite = true;
tacticalCallsign = data["tacticalCallsign"] | ""; tacticalCallsign = data["tacticalCallsign"] | "";
if (!data["aprs_is"].containsKey("active") || if (!data["aprs_is"].containsKey("active") ||
!data["aprs_is"].containsKey("passcode") || !data["aprs_is"].containsKey("passcode") ||
!data["aprs_is"].containsKey("server") || !data["aprs_is"].containsKey("server") ||
@@ -300,14 +300,14 @@ bool Configuration::readFile() {
loramodule.rxFreq = data["lora"]["rxFreq"] | 433775000; loramodule.rxFreq = data["lora"]["rxFreq"] | 433775000;
loramodule.rxSpreadingFactor = data["lora"]["rxSpreadingFactor"] | 12; loramodule.rxSpreadingFactor = data["lora"]["rxSpreadingFactor"] | 12;
loramodule.rxCodingRate4 = data["lora"]["rxCodingRate4"] | 5; loramodule.rxCodingRate4 = data["lora"]["rxCodingRate4"] | 5;
loramodule.rxSignalBandwidth = data["lora"]["rxSignalBandwidth"] | 125000; loramodule.rxSignalBandwidth = data["lora"]["rxSignalBandwidth"] | 125000;
loramodule.txActive = data["lora"]["txActive"] | false; loramodule.txActive = data["lora"]["txActive"] | false;
loramodule.txFreq = data["lora"]["txFreq"] | 433775000; loramodule.txFreq = data["lora"]["txFreq"] | 433775000;
loramodule.txSpreadingFactor = data["lora"]["txSpreadingFactor"] | 12; loramodule.txSpreadingFactor = data["lora"]["txSpreadingFactor"] | 12;
loramodule.txCodingRate4 = data["lora"]["txCodingRate4"] | 5; loramodule.txCodingRate4 = data["lora"]["txCodingRate4"] | 5;
loramodule.txSignalBandwidth = data["lora"]["txSignalBandwidth"] | 125000; loramodule.txSignalBandwidth = data["lora"]["txSignalBandwidth"] | 125000;
loramodule.power = data["lora"]["power"] | 20; loramodule.power = data["lora"]["power"] | 20;
if (!data["display"].containsKey("alwaysOn") || if (!data["display"].containsKey("alwaysOn") ||
!data["display"].containsKey("timeout") || !data["display"].containsKey("timeout") ||
!data["display"].containsKey("turn180")) needsRewrite = true; !data["display"].containsKey("turn180")) needsRewrite = true;
@@ -381,7 +381,7 @@ bool Configuration::readFile() {
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; mqtt.beaconOverMqtt = data["mqtt"]["beaconOverMqtt"] | false;
if (!data["ota"].containsKey("username") || if (!data["ota"].containsKey("username") ||
!data["ota"].containsKey("password")) needsRewrite = true; !data["ota"].containsKey("password")) needsRewrite = true;
ota.username = data["ota"]["username"] | ""; ota.username = data["ota"]["username"] | "";
@@ -426,7 +426,7 @@ bool Configuration::readFile() {
writeFile(); writeFile();
delay(1000); delay(1000);
ESP.restart(); ESP.restart();
} }
Serial.println("Config read successfuly"); Serial.println("Config read successfuly");
return true; return true;
} else { } else {
@@ -434,7 +434,7 @@ bool Configuration::readFile() {
return false; return false;
} }
} }
void Configuration::setDefaultValues() { void Configuration::setDefaultValues() {
WiFi_AP wifiap; WiFi_AP wifiap;
@@ -470,14 +470,14 @@ void Configuration::setDefaultValues() {
beacon.sendViaAPRSIS = true; beacon.sendViaAPRSIS = true;
beacon.sendViaRF = false; beacon.sendViaRF = false;
beacon.beaconFreq = 1; beacon.beaconFreq = 1;
beacon.statusActive = false; beacon.statusActive = false;
beacon.statusPacket = ""; beacon.statusPacket = "";
beacon.gpsActive = false; beacon.gpsActive = false;
beacon.ambiguityLevel = 0; beacon.ambiguityLevel = 0;
personalNote = ""; personalNote = "";
blacklist = ""; blacklist = "";
@@ -500,7 +500,7 @@ void Configuration::setDefaultValues() {
display.alwaysOn = true; display.alwaysOn = true;
display.timeout = 4; display.timeout = 4;
display.turn180 = false; display.turn180 = false;
battery.sendInternalVoltage = false; battery.sendInternalVoltage = false;
battery.monitorInternalVoltage = false; battery.monitorInternalVoltage = false;
battery.internalSleepVoltage = 2.9; battery.internalSleepVoltage = 2.9;
+82 -85
View File
@@ -43,95 +43,91 @@ extern bool backupDigiMode;
namespace DIGI_Utils { namespace DIGI_Utils {
String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) { String cleanPathAsterisks(String path) {
if (!crossFreq) { String terms[] = {",WIDE1*", ",WIDE2*", "*"};
String packetToRepeat = packet.substring(0, packet.indexOf(",") + 1); for (String term : terms) {
String tempPath = path; int index = path.indexOf(term);
if (index != -1) path.remove(index, term.length()); // less memory than: tempPath.replace("*", "");
}
return path;
}
if (path.indexOf("WIDE1-1") != -1 && (Config.digi.mode == 2 || Config.digi.mode == 3)) { String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) {
tempPath.replace("WIDE1-1", (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign) + "*"); String stationCallsign = (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign);
} else if (path.indexOf("WIDE2-") != -1 && Config.digi.mode == 3) { String suffix = thirdParty ? ":}" : ":";
if (path.indexOf(",WIDE1*") != -1) { int suffixIndex = packet.indexOf(suffix);
tempPath.remove(path.indexOf(",WIDE1*"), 7); String packetToRepeat;
} if (!crossFreq) {
if (path.indexOf("*") != -1) { int digiMode = Config.digi.mode;
tempPath.remove(path.indexOf("*"), 1); String tempPath = path;
}
if (path.indexOf("WIDE2-1") != -1) { if (tempPath.indexOf("WIDE1-1") != -1 && (digiMode == 2 || digiMode == 3)) { // WIDE1-1
tempPath.replace("WIDE2-1", (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign) + "*"); if (tempPath.indexOf("*") != -1 ) return ""; // "*" shouldn't be in WIDE1-1 (only) type of packet
} else if (path.indexOf("WIDE2-2") != -1) { tempPath.replace("WIDE1-1", stationCallsign + "*");
tempPath.replace("WIDE2-2", (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign) + "*,WIDE2-1"); } else if (tempPath.indexOf("WIDE2-") != -1 && digiMode == 3) { // WIDE2-n Digipeater
tempPath = cleanPathAsterisks(path);
if (tempPath.indexOf("WIDE2-1") != -1) {
tempPath.replace("WIDE2-1", stationCallsign + "*");
} else if (tempPath.indexOf("WIDE2-2") != -1) {
tempPath.replace("WIDE2-2", stationCallsign + "*,WIDE2-1");
} else { } else {
return ""; return "";
} }
} }
packetToRepeat = packet.substring(0, packet.indexOf(",") + 1);
packetToRepeat += tempPath; packetToRepeat += tempPath;
if (thirdParty) {
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":}")));
} else {
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":")));
}
return packetToRepeat;
} else { // CrossFreq Digipeater } else { // CrossFreq Digipeater
String suffix = thirdParty ? ":}" : ":"; packetToRepeat = cleanPathAsterisks(packet.substring(0, suffixIndex));
String packetToRepeat = packet.substring(0, packet.indexOf(suffix)); if (packetToRepeat.indexOf(stationCallsign) != -1) return ""; // stationCallsign shouldn't be in path
String terms[] = {",WIDE1*", ",WIDE2*", "*"};
for (String term : terms) {
int index = packetToRepeat.indexOf(term);
if (index != -1) {
packetToRepeat.remove(index, term.length());
}
}
packetToRepeat += ","; packetToRepeat += ",";
packetToRepeat += (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign); packetToRepeat += stationCallsign;
packetToRepeat += "*"; packetToRepeat += "*";
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(suffix)));
return packetToRepeat;
} }
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(suffixIndex));
return packetToRepeat;
} }
String generateDigipeatedPacket(const String& packet, bool thirdParty){ String generateDigipeatedPacket(const String& packet, bool thirdParty){
String temp; String temp;
if (thirdParty) { // only header is used if (thirdParty) { // only header is used
const String& header = packet.substring(0, packet.indexOf(":}")); const String& header = packet.substring(0, packet.indexOf(":}"));
temp = header.substring(header.indexOf(">") + 1); temp = header.substring(header.indexOf(">") + 1);
} else { } else {
temp = packet.substring(packet.indexOf(">") + 1, packet.indexOf(":")); temp = packet.substring(packet.indexOf(">") + 1, packet.indexOf(":"));
} }
if (temp.indexOf(",") > 2) { // checks for path in temp int commaIndex = temp.indexOf(",");
const String& path = temp.substring(temp.indexOf(",") + 1); // extract path after tocall int digiMode = Config.digi.mode;
if (Config.digi.mode == 2 || backupDigiMode) { bool crossFreq = abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000; // CrossFreq Digi
if (path.indexOf("WIDE1-1") != - 1) {
return buildPacket(path, packet, thirdParty, false);
} else if (path.indexOf("WIDE1-1") == -1 && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { // CrossFreq Digi
return buildPacket(path, packet, thirdParty, true);
} else {
return "";
}
} else if (Config.digi.mode == 3) {
if (path.indexOf("WIDE1-1") != -1 || path.indexOf("WIDE2-") != -1) {
int wide1Index = path.indexOf("WIDE1-1");
int wide2Index = path.indexOf("WIDE2-");
// WIDE1-1 && WIDE2-n / only WIDE1-1 / only WIDE2-n if (commaIndex > 2) { // "path" found
if ((wide1Index != -1 && wide2Index != -1 && wide1Index < wide2Index) || (wide1Index != -1 && wide2Index == -1) || (wide1Index == -1 && wide2Index != -1)) { const String& path = temp.substring(commaIndex + 1);
return buildPacket(path, packet, thirdParty, false); if (digiMode == 2 || backupDigiMode) {
} bool hasWide = path.indexOf("WIDE1-1") != -1;
return ""; if (hasWide || crossFreq) {
} else if (path.indexOf("WIDE1-1") == -1 && path.indexOf("WIDE2-") == -1 && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { // CrossFreq Digi return buildPacket(path, packet, thirdParty, !hasWide);
return buildPacket(path, packet, thirdParty, true);
} else {
return "";
} }
} else {
return ""; return "";
} }
} else if (temp.indexOf(",") == -1 && (Config.digi.mode == 2 || backupDigiMode || Config.digi.mode == 3) && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { if (digiMode == 3) {
return buildPacket("", packet, thirdParty, true); int wide1Index = path.indexOf("WIDE1-1");
} else { int wide2Index = path.indexOf("WIDE2-");
bool hasWide1 = wide1Index != -1;
bool hasWide2 = wide2Index != -1;
if (hasWide1 && hasWide2 && wide2Index < wide1Index) return ""; // check that WIDE1 before WIDE2
if (hasWide1 || hasWide2) return buildPacket(path, packet, thirdParty, false); // regular APRS with WIDEn-N
if (crossFreq) return buildPacket(path, packet, thirdParty, true); // CrossFreq (without WIDE)
return "";
}
return ""; return "";
} }
if (commaIndex == -1 && (digiMode == 2 || backupDigiMode || digiMode == 3) && crossFreq) return buildPacket("", packet, thirdParty, true); // no "path" but is CrossFreq Digi
return "";
} }
void processLoRaPacket(const String& packet) { void processLoRaPacket(const String& packet) {
@@ -149,31 +145,32 @@ namespace DIGI_Utils {
Sender = packet.substring(3, packet.indexOf(">")); Sender = packet.substring(3, packet.indexOf(">"));
} }
if (Sender == (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign)) return; // Avoid listening to self packets String stationCallsign = Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign;
if (Sender == stationCallsign) return; // Avoid listening to self packets
if (!thirdPartyPacket && Config.tacticalCallsign == "" && !Utils::callsignIsValid(Sender)) return; // No thirdParty + no tactical y no valid callsign if (!thirdPartyPacket && Config.tacticalCallsign == "" && !Utils::callsignIsValid(Sender)) return; // No thirdParty + no tactical y no valid callsign
if (STATION_Utils::check25SegBuffer(Sender, temp.substring(temp.indexOf(":") + 2))) { if (STATION_Utils::isIn25SegHashBuffer(Sender, temp.substring(temp.indexOf(":") + 2))) return;
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(temp, 2); // Digi STATION_Utils::updateLastHeard(Sender);
bool queryMessage = false; Utils::typeOfPacket(temp, 2); // Digi
if (temp.indexOf("::") > 10) { // it's a message bool queryMessage = false;
String AddresseeAndMessage = temp.substring(temp.indexOf("::") + 2); int doubleColonIndex = temp.indexOf("::");
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); if (doubleColonIndex > 10) { // it's a message
Addressee.trim(); String AddresseeAndMessage = temp.substring(doubleColonIndex + 2);
if (Addressee == (Config.tacticalCallsign == "" ? Config.callsign : Config.tacticalCallsign)) { // it's a message for me! String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage, thirdPartyPacket); Addressee.trim();
} if (Addressee == stationCallsign) { // it's a message for me!
} queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage, thirdPartyPacket);
if (!queryMessage) {
String loraPacket = generateDigipeatedPacket(packet.substring(3), thirdPartyPacket);
if (loraPacket != "") {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
if (Config.digi.ecoMode != 1) displayToggle(true);
lastScreenOn = millis();
}
} }
} }
//} if (queryMessage) return; // answer should not be repeated.
String loraPacket = generateDigipeatedPacket(packet.substring(3), thirdPartyPacket);
if (loraPacket != "") {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
if (Config.digi.ecoMode != 1) displayToggle(true);
lastScreenOn = millis();
}
} }
} }
+7 -7
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -26,7 +26,7 @@
#ifdef HAS_TFT #ifdef HAS_TFT
#include <TFT_eSPI.h> #include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI(); TFT_eSPI tft = TFT_eSPI();
TFT_eSprite sprite = TFT_eSprite(&tft); TFT_eSprite sprite = TFT_eSprite(&tft);
#ifdef HELTEC_WIRELESS_TRACKER #ifdef HELTEC_WIRELESS_TRACKER
@@ -176,7 +176,7 @@ void displayToggle(bool toggle) {
#else #else
if (displayFound) display.ssd1306_command(SSD1306_DISPLAYOFF); if (displayFound) display.ssd1306_command(SSD1306_DISPLAYOFF);
#endif #endif
#endif #endif
#endif #endif
} }
+4 -2
View File
@@ -134,15 +134,17 @@ namespace GPS_Utils {
} }
String Latitude = infoGPS.substring(0,8); // First 8 characters are Latitude String Latitude = infoGPS.substring(0,8); // First 8 characters are Latitude
int latitudeColonIndex = Latitude.indexOf(".");
float convertedLatitude = Latitude.substring(0,2).toFloat(); // First 2 digits (Degrees) float convertedLatitude = Latitude.substring(0,2).toFloat(); // First 2 digits (Degrees)
convertedLatitude += Latitude.substring(2,4).toFloat() / 60; // Next 2 digits (Minutes) convertedLatitude += Latitude.substring(2,4).toFloat() / 60; // Next 2 digits (Minutes)
convertedLatitude += Latitude.substring(Latitude.indexOf(".") + 1, Latitude.indexOf(".") + 3).toFloat() / (60*100); convertedLatitude += Latitude.substring(latitudeColonIndex + 1, latitudeColonIndex + 3).toFloat() / (60*100);
if (Latitude.endsWith("S")) convertedLatitude = -convertedLatitude; // Handle Southern Hemisphere if (Latitude.endsWith("S")) convertedLatitude = -convertedLatitude; // Handle Southern Hemisphere
String Longitude = infoGPS.substring(9,18); // Next 9 characters are Longitude String Longitude = infoGPS.substring(9,18); // Next 9 characters are Longitude
int longitudeColonIndex = Longitude.indexOf(".");
float convertedLongitude = Longitude.substring(0,3).toFloat(); // First 3 digits (Degrees) float convertedLongitude = Longitude.substring(0,3).toFloat(); // First 3 digits (Degrees)
convertedLongitude += Longitude.substring(3,5).toFloat() / 60; // Next 2 digits (Minutes) convertedLongitude += Longitude.substring(3,5).toFloat() / 60; // Next 2 digits (Minutes)
convertedLongitude += Longitude.substring(Longitude.indexOf(".") + 1, Longitude.indexOf(".") + 3).toFloat() / (60*100); convertedLongitude += Longitude.substring(longitudeColonIndex + 1, longitudeColonIndex + 3).toFloat() / (60*100);
if (Longitude.endsWith("W")) convertedLongitude = -convertedLongitude; // Handle Western Hemisphere if (Longitude.endsWith("W")) convertedLongitude = -convertedLongitude; // Handle Western Hemisphere
return buildDistanceAndComment(convertedLatitude, convertedLongitude, infoGPS.substring(19)); return buildDistanceAndComment(convertedLatitude, convertedLongitude, infoGPS.substring(19));
+13 -13
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -29,17 +29,16 @@ bool validateKISSFrame(const String& kissFormattedFrame) {
} }
String encodeAddressAX25(String tnc2Address) { String encodeAddressAX25(String tnc2Address) {
bool hasBeenDigipited = tnc2Address.indexOf('*') != -1; bool hasBeenDigipited = tnc2Address.indexOf('*') != -1;
int tnc2AddressIndex = tnc2Address.indexOf('-');
if (tnc2Address.indexOf('-') == -1) { if (tnc2AddressIndex == -1) {
if (hasBeenDigipited) { if (hasBeenDigipited) {
tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1); tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1);
} }
tnc2Address += "-0"; tnc2Address += "-0";
} }
int separatorIndex = tnc2Address.indexOf('-'); int separatorIndex = tnc2AddressIndex;
int ssid = tnc2Address.substring(separatorIndex + 1).toInt(); int ssid = tnc2Address.substring(separatorIndex + 1).toInt();
String kissAddress = ""; String kissAddress = "";
@@ -131,8 +130,9 @@ String encodeKISS(const String& frame) {
if (validateTNC2Frame(frame)) { if (validateTNC2Frame(frame)) {
String address = ""; String address = "";
bool dstAddresWritten = false; bool dstAddresWritten = false;
for (int p = 0; p <= frame.indexOf(':'); p++) { int colonFrameIndex = frame.indexOf(':');
for (int p = 0; p <= colonFrameIndex; p++) {
char currentChar = frame.charAt(p); char currentChar = frame.charAt(p);
if (currentChar == ':' || currentChar == '>' || currentChar == ',') { if (currentChar == ':' || currentChar == '>' || currentChar == ',') {
if (!dstAddresWritten && (currentChar == ',' || currentChar == ':')) { if (!dstAddresWritten && (currentChar == ',' || currentChar == ':')) {
@@ -151,7 +151,7 @@ String encodeKISS(const String& frame) {
ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK)); ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK));
ax25Frame += (char)APRS_CONTROL_FIELD; ax25Frame += (char)APRS_CONTROL_FIELD;
ax25Frame += (char)APRS_INFORMATION_FIELD; ax25Frame += (char)APRS_INFORMATION_FIELD;
ax25Frame += frame.substring(frame.indexOf(':') + 1); ax25Frame += frame.substring(colonFrameIndex + 1);
} }
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA); String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);
+9 -9
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -43,7 +43,7 @@ bool transmitFlag = true;
#ifdef HAS_SX1268 #ifdef HAS_SX1268
#if defined(LIGHTGATEWAY_1_0) || defined(LIGHTGATEWAY_PLUS_1_0) #if defined(LIGHTGATEWAY_1_0) || defined(LIGHTGATEWAY_PLUS_1_0)
SPIClass loraSPI(FSPI); SPIClass loraSPI(FSPI);
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN, loraSPI); SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN, loraSPI);
#else #else
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
#endif #endif
@@ -100,11 +100,11 @@ namespace LoRa_Utils {
while (true); while (true);
} }
#endif*/ #endif*/
radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor); radio.setSpreadingFactor(Config.loramodule.rxSpreadingFactor);
radio.setCodingRate(Config.loramodule.rxCodingRate4); radio.setCodingRate(Config.loramodule.rxCodingRate4);
float signalBandwidth = Config.loramodule.rxSignalBandwidth / 1000; float signalBandwidth = Config.loramodule.rxSignalBandwidth / 1000;
radio.setBandwidth(signalBandwidth); radio.setBandwidth(signalBandwidth);
radio.setCRC(true); radio.setCRC(true);
#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)
@@ -174,7 +174,7 @@ namespace LoRa_Utils {
changeFreqTx(); changeFreqTx();
} }
} }
#ifdef INTERNAL_LED_PIN #ifdef INTERNAL_LED_PIN
if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, HIGH); // disabled in Ultra Eco Mode if (Config.digi.ecoMode != 1) digitalWrite(INTERNAL_LED_PIN, HIGH); // disabled in Ultra Eco Mode
#endif #endif
+6 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -95,7 +95,7 @@ namespace MQTT_Utils {
void setup() { void setup() {
if (!Config.mqtt.active) return; if (!Config.mqtt.active) return;
pubSub.setClient(mqttClient); pubSub.setClient(mqttClient);
pubSub.setCallback(receivedFromMqtt); pubSub.setCallback(receivedFromMqtt);
} }
} }
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+5 -5
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
+15 -36
View File
@@ -49,40 +49,23 @@ extern bool stationCallsignIsValid;
namespace POWER_Utils { namespace POWER_Utils {
#ifdef VEXT_CTRL #ifdef ADC_CTRL_PIN
void vext_ctrl_ON() {
#if VEXT_CTRL_INVERTED == 1
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? HIGH : LOW);
#else
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? LOW : HIGH);
#endif
}
void vext_ctrl_OFF() {
#if VEXT_CTRL_INVERTED == 1
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? LOW : HIGH);
#else
digitalWrite(VEXT_CTRL, Config.digi.ecoMode == 1 ? HIGH : LOW);
#endif
}
#endif
#ifdef ADC_CTRL
void adc_ctrl_ON() { void adc_ctrl_ON() {
#if ADC_CTRL_INVERTED == 1 digitalWrite(ADC_CTRL_PIN, ADC_CTRL_ON_STATE);
digitalWrite(ADC_CTRL, LOW);
#else
digitalWrite(ADC_CTRL, HIGH);
#endif
} }
void adc_ctrl_OFF() { void adc_ctrl_OFF() {
#if ADC_CTRL_INVERTED == 1 digitalWrite(ADC_CTRL_PIN, !ADC_CTRL_ON_STATE);
digitalWrite(ADC_CTRL, HIGH); }
#else #endif
digitalWrite(ADC_CTRL, LOW);
#endif #ifdef VEXT_CTRL_PIN
void vext_ctrl_ON() {
digitalWrite(VEXT_CTRL_PIN, Config.digi.ecoMode == 1 ? !VEXT_CTRL_ON_STATE : VEXT_CTRL_ON_STATE);
}
void vext_ctrl_OFF() {
digitalWrite(VEXT_CTRL_PIN, Config.digi.ecoMode == 1 ? VEXT_CTRL_ON_STATE : !VEXT_CTRL_ON_STATE);
} }
#endif #endif
@@ -313,12 +296,8 @@ namespace POWER_Utils {
Wire.begin(OLED_SDA, OLED_SCL); Wire.begin(OLED_SDA, OLED_SCL);
#endif #endif
#ifdef USE_WIRE_WITH_BOARD_I2C_PINS #ifdef SENSOR_I2C_BUS
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL); SENSOR_I2C_BUS.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#ifdef USE_WIRE1_WITH_BOARD_I2C_PINS
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif #endif
delay(1000); delay(1000);
+23 -21
View File
@@ -77,10 +77,14 @@ namespace QUERY_Utils {
answer.concat("?WHERE on development 73!"); answer.concat("?WHERE on development 73!");
} */ } */
else if (STATION_Utils::isManager(station) && (!queryFromAPRSIS || !Config.remoteManagement.rfOnly)) { else if (STATION_Utils::isManager(station) && (!queryFromAPRSIS || !Config.remoteManagement.rfOnly)) {
if (queryQuestion.indexOf("?EM=OFF") == 0) { int digiMode = Config.digi.mode;
if ((Config.digi.mode == 2 || Config.digi.mode == 3) && Config.loramodule.txActive && Config.loramodule.rxActive && !Config.aprs_is.active) { int digiEcoMode = Config.digi.ecoMode;
if (Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) { // Exit Digipeater EcoMode or Digipeater without WiFiAP int radioTxActive = Config.loramodule.txActive;
answer = (Config.digi.ecoMode == 1) ? "DigiEcoMode:OFF" : "Digipeater + WiFiAP enabled"; bool onlyRadioActive = radioTxActive && Config.loramodule.rxActive && !Config.aprs_is.active;
if (queryQuestion.startsWith("?EM=OFF")) {
if ((digiMode == 2 || digiMode == 3) && onlyRadioActive) {
if (digiEcoMode == 1 || digiEcoMode == 2) { // Exit Digipeater EcoMode or Digipeater without WiFiAP
answer = (digiEcoMode == 1) ? "DigiEcoMode:OFF" : "Digipeater + WiFiAP enabled";
Config.digi.ecoMode = 0; Config.digi.ecoMode = 0;
Config.display.alwaysOn = true; Config.display.alwaysOn = true;
Config.display.timeout = 10; Config.display.timeout = 10;
@@ -92,9 +96,9 @@ namespace QUERY_Utils {
} else { } else {
answer = "Digipeater Mode control not possible"; answer = "Digipeater Mode control not possible";
} }
} else if (queryQuestion.indexOf("?EM=ON") == 0) { } else if (queryQuestion.startsWith("?EM=ON")) {
if ((Config.digi.mode == 2 || Config.digi.mode == 3) && Config.loramodule.txActive && Config.loramodule.rxActive && !Config.aprs_is.active) { if ((digiMode == 2 || digiMode == 3) && onlyRadioActive) {
if (Config.digi.ecoMode == 0) { // Start Digipeater EcoMode if (digiEcoMode == 0) { // Start Digipeater EcoMode
answer = "DigiEcoMode:ON"; answer = "DigiEcoMode:ON";
Config.digi.ecoMode = 1; Config.digi.ecoMode = 1;
shouldSleepLowVoltage = true; // to make sure all packets in outputPacketBuffer are sent before restart. shouldSleepLowVoltage = true; // to make sure all packets in outputPacketBuffer are sent before restart.
@@ -105,31 +109,29 @@ namespace QUERY_Utils {
} else { } else {
answer = "Digipeater Mode control not possible"; answer = "Digipeater Mode control not possible";
} }
} else if (queryQuestion.indexOf("?EM=?") == 0) { // Digipeater EcoMode Status } else if (queryQuestion.startsWith("?EM=?")) { // Digipeater EcoMode Status
if (Config.digi.ecoMode == 0) { switch (digiEcoMode) {
answer = "DigiEcoMode:OFF"; case 0: answer = "DigiEcoMode:OFF"; break;
} else if (Config.digi.ecoMode == 1) { case 1: answer = "DigiEcoMode:ON"; break;
answer = "DigiEcoMode:ON"; default: answer = "DigiEcoMode:OFF/Only Serial Output";
} else {
answer = "DigiEcoMode:OFF/Only Serial Output";
} }
} else if (queryQuestion.indexOf("?TX=ON") == 0) { } else if (queryQuestion.startsWith("?TX=ON")) {
if (Config.loramodule.txActive) { if (radioTxActive) {
answer = "TX was ON"; answer = "TX was ON";
} else { } else {
Config.loramodule.txActive = true; Config.loramodule.txActive = true;
answer = "TX=ON"; answer = "TX=ON";
} }
} else if (queryQuestion.indexOf("?TX=OFF") == 0) { } else if (queryQuestion.startsWith("?TX=OFF")) {
if (!Config.loramodule.txActive) { if (!radioTxActive) {
answer = "TX was OFF"; answer = "TX was OFF";
} else { } else {
Config.loramodule.txActive = false; Config.loramodule.txActive = false;
answer = "TX=OFF"; answer = "TX=OFF";
} }
} else if (queryQuestion.indexOf("?TX=?") == 0) { } else if (queryQuestion.startsWith("?TX=?")) {
answer = (Config.loramodule.txActive) ? "TX=ON" : "TX=OFF"; answer = (radioTxActive) ? "TX=ON" : "TX=OFF";
} else if (queryQuestion.indexOf("?COMMIT") == 0) { // saving for next reboot } else if (queryQuestion.startsWith("?COMMIT")) { // saving for next reboot
answer = "New Config Saved"; answer = "New Config Saved";
Config.writeFile(); Config.writeFile();
} }
+62 -53
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -25,6 +25,8 @@
#include "utils.h" #include "utils.h"
#include <vector> #include <vector>
#define SECS_TO_WAIT 3 // soon to be deleted...
extern Configuration Config; extern Configuration Config;
extern uint32_t lastRxTime; extern uint32_t lastRxTime;
@@ -40,17 +42,16 @@ std::vector<LastHeardStation> lastHeardObjects;
struct OutputPacketBuffer { struct OutputPacketBuffer {
String packet; String packet;
bool isBeacon; bool isBeacon;
OutputPacketBuffer(const String& p, bool b) : packet(p), isBeacon(b) {}
}; };
std::vector<OutputPacketBuffer> outputPacketBuffer; std::vector<OutputPacketBuffer> outputPacketBuffer;
struct Packet25SegBuffer { struct Packet25SegBuffer {
uint32_t receivedTime; uint32_t receivedTime;
String station; uint32_t hash;
String payload;
}; };
std::vector<Packet25SegBuffer> packet25SegBuffer; std::vector<Packet25SegBuffer> packet25SegBuffer;
bool saveNewDigiEcoModeConfig = false; bool saveNewDigiEcoModeConfig = false;
bool packetIsBeacon = false; bool packetIsBeacon = false;
@@ -59,19 +60,18 @@ namespace STATION_Utils {
std::vector<String> loadCallsignList(const String& list) { std::vector<String> loadCallsignList(const String& list) {
std::vector<String> loadedList; std::vector<String> loadedList;
int start = 0;
int listLength = list.length();
String callsigns = list; while (start < listLength) {
callsigns.trim(); while (start < listLength && list[start] == ' ') start++; // avoid blank spaces
if (start >= listLength) break;
while (callsigns.length() > 0) { // != "" int end = start;
int spaceIndex = callsigns.indexOf(" "); while (end < listLength && list[end] != ' ') end++; // find another blank space or reach listLength
if (spaceIndex == -1) { // No more spaces, add the last part
loadedList.push_back(callsigns); loadedList.emplace_back(list.substring(start, end));
break; start = end + 1; // keep on searching if listLength not reached
}
loadedList.push_back(callsigns.substring(0, spaceIndex));
callsigns = callsigns.substring(spaceIndex + 1);
callsigns.trim(); // Trim in case of multiple spaces
} }
return loadedList; return loadedList;
} }
@@ -85,8 +85,9 @@ namespace STATION_Utils {
for (size_t i = 0; i < list.size(); i++) { for (size_t i = 0; i < list.size(); i++) {
int wildcardIndex = list[i].indexOf("*"); int wildcardIndex = list[i].indexOf("*");
if (wildcardIndex >= 0) { if (wildcardIndex >= 0) {
String wildcard = list[i].substring(0, wildcardIndex); if (wildcardIndex >= 2 && callsign.length() >= wildcardIndex && strncmp(callsign.c_str(), list[i].c_str(), wildcardIndex) == 0) {
if (callsign.startsWith(wildcard)) return true; return true;
}
} else { } else {
if (list[i] == callsign) return true; if (list[i] == callsign) return true;
} }
@@ -127,36 +128,33 @@ namespace STATION_Utils {
} }
void deleteNotHeard() { void deleteNotHeard() {
std::vector<LastHeardStation> lastHeardStation_temp; uint32_t currentTime = millis();
for (int i = 0; i < lastHeardStations.size(); i++) { uint32_t timeout = Config.rememberStationTime * 60UL * 1000UL;
if (millis() - lastHeardStations[i].lastHeardTime < Config.rememberStationTime * 60 * 1000) {
lastHeardStation_temp.push_back(lastHeardStations[i]); for (int i = lastHeardStations.size() - 1; i >= 0; i--) {
if (currentTime - lastHeardStations[i].lastHeardTime >= timeout) {
lastHeardStations.erase(lastHeardStations.begin() + i);
} }
} }
lastHeardStations.clear();
for (int j = 0; j < lastHeardStation_temp.size(); j++) {
lastHeardStations.push_back(lastHeardStation_temp[j]);
}
lastHeardStation_temp.clear();
} }
void updateLastHeard(const String& station) { void updateLastHeard(const String& station) {
deleteNotHeard(); deleteNotHeard();
bool stationHeard = false; uint32_t currentTime = millis();
for (int i = 0; i < lastHeardStations.size(); i++) { for (size_t i = 0; i < lastHeardStations.size(); i++) {
if (lastHeardStations[i].station == station) { if (lastHeardStations[i].station == station) {
lastHeardStations[i].lastHeardTime = millis(); lastHeardStations[i].lastHeardTime = currentTime;
stationHeard = true; Utils::showActiveStations();
break; return;
} }
} }
if (!stationHeard) lastHeardStations.emplace_back(LastHeardStation{millis(), station}); lastHeardStations.emplace_back(LastHeardStation{currentTime, station});
Utils::showActiveStations(); Utils::showActiveStations();
} }
bool wasHeard(const String& station) { bool wasHeard(const String& station) {
deleteNotHeard(); deleteNotHeard();
for (int i = 0; i < lastHeardStations.size(); i++) { for (size_t i = 0; i < lastHeardStations.size(); i++) {
if (lastHeardStations[i].station == station) { if (lastHeardStations[i].station == station) {
Utils::println(" ---> Listened Station"); Utils::println(" ---> Listened Station");
return true; return true;
@@ -166,18 +164,33 @@ namespace STATION_Utils {
return false; return false;
} }
void clean25SegBuffer() { void clean25SegHashBuffer() {
if (!packet25SegBuffer.empty() && (millis() - packet25SegBuffer[0].receivedTime) > 25 * 1000) packet25SegBuffer.erase(packet25SegBuffer.begin()); uint32_t currentTime = millis();
} for (int i = packet25SegBuffer.size() - 1; i >= 0; i--) {
if ((currentTime - packet25SegBuffer[i].receivedTime) > 25 * 1000) {
bool check25SegBuffer(const String& station, const String& textMessage) { packet25SegBuffer.erase(packet25SegBuffer.begin() + i);
if (!packet25SegBuffer.empty()) {
for (int i = 0; i < packet25SegBuffer.size(); i++) {
if (packet25SegBuffer[i].station == station && packet25SegBuffer[i].payload == textMessage) return false;
} }
} }
packet25SegBuffer.emplace_back(Packet25SegBuffer{millis(), station, textMessage}); }
return true;
uint32_t makeHash(const String& station, const String& payload) { // DJB2 Hash
uint32_t h = 5381;
for (size_t i = 0; i < station.length(); i++)
h = ((h << 5) + h) + station[i];
for (size_t i = 0; i < payload.length(); i++)
h = ((h << 5) + h) + payload[i];
return h;
}
bool isIn25SegHashBuffer(const String& station, const String& textMessage) {
clean25SegHashBuffer();
uint32_t newHash = makeHash(station, textMessage);
uint32_t currentTime = millis();
for (int i = 0; i < packet25SegBuffer.size(); i++) {
if (packet25SegBuffer[i].hash == newHash) return true;
}
packet25SegBuffer.push_back({currentTime, newHash});
return false;
} }
void processOutputPacketBufferUltraEcoMode() { void processOutputPacketBufferUltraEcoMode() {
@@ -201,7 +214,7 @@ namespace STATION_Utils {
} }
void processOutputPacketBuffer() { void processOutputPacketBuffer() {
int timeToWait = 3 * 1000; // 3 segs between packet Tx and also Rx ??? int timeToWait = SECS_TO_WAIT * 1000; // 3 segs between packet Tx and also Rx ???
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) {
@@ -229,11 +242,7 @@ namespace STATION_Utils {
} }
void addToOutputPacketBuffer(const String& packet, bool flag) { void addToOutputPacketBuffer(const String& packet, bool flag) {
OutputPacketBuffer entry; outputPacketBuffer.emplace_back(OutputPacketBuffer{packet, flag});
entry.packet = packet;
entry.isBeacon = flag;
outputPacketBuffer.push_back(entry);
} }
} }
+13 -12
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -43,9 +43,11 @@ namespace SYSLOG_Utils {
char signalData[35]; char signalData[35];
snprintf(signalData, sizeof(signalData), " / %ddBm / %.2fdB / %dHz", rssi, snr, freqError); snprintf(signalData, sizeof(signalData), " / %ddBm / %.2fdB / %dHz", rssi, snr, freqError);
int colonIndex = packet.indexOf(":"); int colonIndex = packet.indexOf(":");
char nextChar = packet[colonIndex + 1]; char nextChar = packet[colonIndex + 1];
String sender = packet.substring(3, packet.indexOf(">")); int greaterThanIndex = packet.indexOf(">");
int telemetryPacketIndex = packet.indexOf(":T#");
String sender = packet.substring(3, greaterThanIndex);
switch (type) { switch (type) {
case 0: // CRC case 0: // CRC
@@ -58,13 +60,12 @@ namespace SYSLOG_Utils {
if (nextChar == ':') { if (nextChar == ':') {
syslogPacket.concat("MESSAGE / "); syslogPacket.concat("MESSAGE / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(colonIndex + 2)); syslogPacket.concat(packet.substring(colonIndex + 2));
} else if (nextChar == '!' || nextChar == '=' || nextChar == '@') { } else if (nextChar == '!' || nextChar == '=' || nextChar == '@') {
syslogPacket.concat("GPS / "); syslogPacket.concat("GPS / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" / "); syslogPacket.concat(" / ");
int greaterThanIndex = packet.indexOf(">");
if (packet.indexOf("WIDE1-1") > 10) { if (packet.indexOf("WIDE1-1") > 10) {
syslogPacket.concat(packet.substring(greaterThanIndex + 1, packet.indexOf(","))); syslogPacket.concat(packet.substring(greaterThanIndex + 1, packet.indexOf(",")));
syslogPacket.concat(" / WIDE1-1"); syslogPacket.concat(" / WIDE1-1");
@@ -87,11 +88,11 @@ namespace SYSLOG_Utils {
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(colonIndex + 2)); syslogPacket.concat(packet.substring(colonIndex + 2));
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) { } else if (telemetryPacketIndex >= 10 && packet.indexOf(":=/") == -1) {
syslogPacket.concat("TELEMETRY / "); syslogPacket.concat("TELEMETRY / ");
syslogPacket.concat(sender); syslogPacket.concat(sender);
syslogPacket.concat(" ---> "); syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf(":T#") + 3)); syslogPacket.concat(packet.substring(telemetryPacketIndex + 3));
} else { } else {
syslogPacket.concat(packet); syslogPacket.concat(packet);
} }
+18 -10
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -29,10 +29,11 @@
#include "display.h" #include "display.h"
extern Configuration Config; extern Configuration Config;
extern bool sendStartTelemetry;
int telemetryCounter = random(1,999); int telemetryCounter = random(1,999);
uint32_t telemetryEUPTime = 0;
bool sendEUP = false; // Equations Units Parameters
namespace TELEMETRY_Utils { namespace TELEMETRY_Utils {
@@ -89,7 +90,7 @@ namespace TELEMETRY_Utils {
sendBaseTelemetryPacket("EQNS.", getEquationCoefficients()); sendBaseTelemetryPacket("EQNS.", getEquationCoefficients());
sendBaseTelemetryPacket("UNIT.", getUnitLabels()); sendBaseTelemetryPacket("UNIT.", getUnitLabels());
sendBaseTelemetryPacket("PARM.", getParameterNames()); sendBaseTelemetryPacket("PARM.", getParameterNames());
sendStartTelemetry = false; sendEUP = false;
} }
String generateEncodedTelemetryBytes(float value, bool counterBytes, byte telemetryType) { String generateEncodedTelemetryBytes(float value, bool counterBytes, byte telemetryType) {
@@ -106,7 +107,7 @@ namespace TELEMETRY_Utils {
case 3: tempValue = (value * 8); break; // Pressure case 3: tempValue = (value * 8); break; // Pressure
default: tempValue = value; break; default: tempValue = value; break;
} }
} }
int firstByte = tempValue / 91; int firstByte = tempValue / 91;
tempValue -= firstByte * 91; tempValue -= firstByte * 91;
@@ -127,4 +128,11 @@ namespace TELEMETRY_Utils {
return telemetry; return telemetry;
} }
void checkEUPInterval() {
if (telemetryEUPTime == 0 || millis() - telemetryEUPTime > 24UL * 60UL * 60UL * 1000UL) {
sendEUP = true;
telemetryEUPTime = millis();
}
}
} }
+6 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -45,7 +45,7 @@ String inputSerialBuffer = "";
namespace TNC_Utils { namespace TNC_Utils {
void setup() { void setup() {
if (Config.tnc.enableServer && Config.digi.ecoMode == 0) { if (Config.tnc.enableServer && Config.digi.ecoMode == 0) {
tncServer.stop(); tncServer.stop();
+46 -34
View File
@@ -58,11 +58,12 @@ extern bool backupDigiMode;
extern bool shouldSleepLowVoltage; extern bool shouldSleepLowVoltage;
extern bool transmitFlag; extern bool transmitFlag;
extern bool passcodeValid; extern bool passcodeValid;
extern bool sendEUP; // Equations Units Parameters
extern std::vector<LastHeardStation> lastHeardStations; extern std::vector<LastHeardStation> lastHeardStations;
bool statusAfterBoot = true; bool statusAfterBoot = true;
bool sendStartTelemetry = true;
bool beaconUpdate = false; bool beaconUpdate = false;
uint32_t lastBeaconTx = 0; uint32_t lastBeaconTx = 0;
uint32_t lastScreenOn = millis(); uint32_t lastScreenOn = millis();
@@ -157,7 +158,8 @@ namespace Utils {
if (beaconUpdate) { if (beaconUpdate) {
if (!Config.display.alwaysOn && Config.display.timeout != 0) displayToggle(true); if (!Config.display.alwaysOn && Config.display.timeout != 0) displayToggle(true);
if (sendStartTelemetry && TELEMETRY_Utils::checkEUPInterval();
if (sendEUP &&
Config.battery.sendVoltageAsTelemetry && Config.battery.sendVoltageAsTelemetry &&
!Config.wxsensor.active && !Config.wxsensor.active &&
(Config.battery.sendInternalVoltage || Config.battery.sendExternalVoltage) && (Config.battery.sendInternalVoltage || Config.battery.sendExternalVoltage) &&
@@ -312,7 +314,6 @@ namespace Utils {
} }
void typeOfPacket(const String& packet, const uint8_t packetType) { void typeOfPacket(const String& packet, const uint8_t packetType) {
String sender = packet.substring(0,packet.indexOf(">"));
switch (packetType) { switch (packetType) {
case 0: // LoRa-APRS case 0: // LoRa-APRS
fifthLine = "LoRa Rx ----> APRS-IS"; fifthLine = "LoRa Rx ----> APRS-IS";
@@ -328,6 +329,7 @@ namespace Utils {
int firstColonIndex = packet.indexOf(":"); int firstColonIndex = packet.indexOf(":");
char nextChar = packet[firstColonIndex + 1]; char nextChar = packet[firstColonIndex + 1];
String sender = packet.substring(0,packet.indexOf(">"));
for (int i = sender.length(); i < 9; i++) { for (int i = sender.length(); i < 9; i++) {
sender += " "; sender += " ";
} }
@@ -417,43 +419,53 @@ namespace Utils {
bool callsignIsValid(const String& callsign) { bool callsignIsValid(const String& callsign) {
if (callsign == "WLNK-1") return true; if (callsign == "WLNK-1") return true;
int totalCallsignLength = callsign.length();
if (totalCallsignLength < 4) return false;
String cleanCallsign; int hyphenIndex = callsign.indexOf("-");
if (callsign.indexOf("-") > 0) { // SSID Validation int baseCallsignLength = (hyphenIndex > 0) ? hyphenIndex : totalCallsignLength;
cleanCallsign = callsign.substring(0, callsign.indexOf("-"));
String ssid = callsign.substring(callsign.indexOf("-") + 1); if (hyphenIndex > 0) { // SSID Validation
if (ssid.indexOf("-") != -1 || ssid.length() > 2) return false; if (hyphenIndex < 4) return false; // base Callsign must have at least 4 characters
if (ssid.length() == 2 && ssid[0] == '0') return false; int ssidStart = hyphenIndex + 1;
for (int i = 0; i < ssid.length(); i++) { int ssidLength = totalCallsignLength - ssidStart;
if (!isAlphaNumeric(ssid[i])) return false; if (ssidLength == 0 || ssidLength > 2) return false;
if (callsign.indexOf('-', ssidStart) != -1) return false; // avoid another "-" in ssid
if (ssidLength == 2 && callsign[ssidStart] == '0') return false; // ssid can't start with "0"
for (int i = ssidStart; i < totalCallsignLength; i++) {
if (!isDigit(callsign[i])) return false;
} }
}
if (baseCallsignLength < 4 || baseCallsignLength > 6) return false;
bool padded = false; // Callsigns with 4 characters like A0AA are padded into 5 characters for further analisis : A0AA --> _A0AA
if (baseCallsignLength == 4 && isAlpha(callsign[0]) && isDigit(callsign[1]) && isAlpha(callsign[2]) && isAlpha(callsign[3])) padded = true;
char c0, c1, c2, c3;
if (padded) {
c0 = ' ';
c1 = callsign[0];
c2 = callsign[1];
c3 = callsign[2];
} else { } else {
cleanCallsign = callsign; c0 = callsign[0];
c1 = callsign[1];
c2 = callsign[2];
c3 = callsign[3];
}
if (!isDigit(c2) || !isAlpha(c3)) { // __0A__ must be validated
if (c0 != 'R' && !isDigit(c1) && !isAlpha(c2)) return false; // to accepto R0A___
} }
if (cleanCallsign.length() < 4 || cleanCallsign.length() > 6) return false; bool isValid =
((isAlphaNumeric(c0) || c0 == ' ') && isAlpha(c1)) || // AA0A (+A+A) + _A0AA (+A) + 0A0A (+A+A)
(isAlpha(c0) && isDigit(c1)) || // A00A (+A+A)
(c0 == 'R' && baseCallsignLength == 6 && isDigit(c1) && isAlpha(c2) && isAlpha(c3) && isAlpha(callsign[4])); // R0AA (+A+A)
if (!isValid) return false; // also 00__ avoided
if (cleanCallsign.length() < 6 && isAlpha(cleanCallsign[0]) && isDigit(cleanCallsign[1]) && isAlpha(cleanCallsign[2]) && isAlpha(cleanCallsign[3]) ) { if (baseCallsignLength > 4 ) { // to validate ____AA
cleanCallsign = " " + cleanCallsign; // A0AA --> _A0AA for (int i = 4; i < baseCallsignLength; i++) {
} if (!isAlpha(callsign[i])) return false;
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) { // to validate ____AA
for (int i = 5; i <= cleanCallsign.length(); i++) {
if (!isAlpha(cleanCallsign[i - 1])) return false;
} }
} }
return true; return true;
+9 -9
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -88,7 +88,7 @@ namespace WEB_Utils {
return request->requestAuthentication(); return request->requestAuthentication();
File file = SPIFFS.open("/igate_conf.json"); File file = SPIFFS.open("/igate_conf.json");
String fileContent; String fileContent;
while(file.available()){ while(file.available()){
fileContent += String((char)file.read()); fileContent += String((char)file.read());
@@ -161,7 +161,7 @@ namespace WEB_Utils {
Config.callsign = getParamStringSafe("callsign", Config.callsign); Config.callsign = getParamStringSafe("callsign", Config.callsign);
Config.tacticalCallsign = getParamStringSafe("tacticalCallsign", Config.tacticalCallsign); Config.tacticalCallsign = getParamStringSafe("tacticalCallsign", Config.tacticalCallsign);
Config.wifiAutoAP.password = getParamStringSafe("wifi.autoAP.password", Config.wifiAutoAP.password); Config.wifiAutoAP.password = getParamStringSafe("wifi.autoAP.password", Config.wifiAutoAP.password);
Config.wifiAutoAP.timeout = getParamIntSafe("wifi.autoAP.timeout", Config.wifiAutoAP.timeout); Config.wifiAutoAP.timeout = getParamIntSafe("wifi.autoAP.timeout", Config.wifiAutoAP.timeout);
@@ -299,7 +299,7 @@ namespace WEB_Utils {
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", ""); AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
response->addHeader("Location", "/?success=1"); response->addHeader("Location", "/?success=1");
request->send(response); request->send(response);
displayToggle(false); displayToggle(false);
delay(500); delay(500);
ESP.restart(); ESP.restart();
@@ -309,7 +309,7 @@ namespace WEB_Utils {
errorPage += "<h1>Configuration Error:</h1>"; errorPage += "<h1>Configuration Error:</h1>";
errorPage += "<p>Couldn't save new configuration. Please try again.</p>"; errorPage += "<p>Couldn't save new configuration. Please try again.</p>";
errorPage += "<a href='/'>Back</a></body></html>"; errorPage += "<a href='/'>Back</a></body></html>";
AsyncWebServerResponse *response = request->beginResponse(500, "text/html", errorPage); AsyncWebServerResponse *response = request->beginResponse(500, "text/html", errorPage);
request->send(response); request->send(response);
} }
+6 -6
View File
@@ -1,17 +1,17 @@
/* Copyright (C) 2025 Ricardo Guzman - CA2RXU /* Copyright (C) 2025 Ricardo Guzman - CA2RXU
* *
* This file is part of LoRa APRS iGate. * This file is part of LoRa APRS iGate.
* *
* LoRa APRS iGate is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* LoRa APRS iGate is distributed in the hope that it will be useful, * LoRa APRS iGate is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>. * along with LoRa APRS iGate. If not, see <https://www.gnu.org/licenses/>.
*/ */
@@ -66,7 +66,7 @@ namespace WIFI_Utils {
backupDigiMode = true; backupDigiMode = true;
WiFi.disconnect(); WiFi.disconnect();
lastBackupDigiTime = currentTime; lastBackupDigiTime = currentTime;
} }
} else { } else {
Serial.println("Reconnecting to WiFi..."); Serial.println("Reconnecting to WiFi...");
WiFi.disconnect(); WiFi.disconnect();
+3 -3
View File
@@ -61,9 +61,9 @@ namespace WX_Utils {
void getWxModuleAddres() { void getWxModuleAddres() {
uint8_t err, addr; uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) { for(addr = 1; addr < 0x7F; addr++) {
#if defined(HELTEC_V3) || defined(HELTEC_V3_2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) #ifdef SENSOR_I2C_BUS
Wire1.beginTransmission(addr); SENSOR_I2C_BUS.beginTransmission(addr);
err = Wire1.endTransmission(); err = SENSOR_I2C_BUS.endTransmission();
#else #else
Wire.beginTransmission(addr); Wire.beginTransmission(addr);
#ifdef LIGHTGATEWAY_PLUS_1_0 #ifdef LIGHTGATEWAY_PLUS_1_0
@@ -31,7 +31,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_38 #define GPIO_WAKEUP_PIN GPIO_SEL_38
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 11 #define BOARD_I2C_SDA 11
#define BOARD_I2C_SCL 12 #define BOARD_I2C_SCL 12
@@ -39,8 +39,8 @@
#define INTERNAL_LED_PIN 48 #define INTERNAL_LED_PIN 48
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define SENSOR_I2C_BUS Wire
#define OLED_SDA 5 #define BOARD_I2C_SDA 5
#define OLED_SCL 6 #define BOARD_I2C_SCL 6
#endif #endif
+3 -2
View File
@@ -48,7 +48,8 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 25 #define INTERNAL_LED_PIN 25
#define BATTERY_PIN 37 #define BATTERY_PIN 37
#define ADC_CTRL 21
#define ADC_CTRL_INVERTED 1 #define ADC_CTRL_PIN 21
#define ADC_CTRL_ON_STATE LOW
#endif #endif
+2 -1
View File
@@ -48,7 +48,8 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 25 #define INTERNAL_LED_PIN 25
#define BATTERY_PIN 37 #define BATTERY_PIN 37
#define ADC_CTRL 21 #define ADC_CTRL 21
#define ADC_CTRL_INVERTED 1 #define ADC_CTRL_ON_STATE LOW
#endif #endif
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 39 #define BOARD_I2C_SDA 39
#define BOARD_I2C_SCL 38 #define BOARD_I2C_SCL 38
@@ -50,9 +50,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 45 #define INTERNAL_LED_PIN 45
#define BATTERY_PIN 7 #define BATTERY_PIN 7
#define ADC_CTRL 46
#define ADC_CTRL_INVERTED 0 #define ADC_CTRL_PIN 46
#define VEXT_CTRL 18 #define ADC_CTRL_ON_STATE HIGH
#define VEXT_CTRL_INVERTED 0 #define VEXT_CTRL_PIN 18
#define VEXT_CTRL_ON_STATE HIGH
#endif #endif
@@ -34,7 +34,7 @@
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -53,9 +53,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define VEXT_CTRL_INVERTED 0 #define ADC_CTRL_PIN 37
#define ADC_CTRL 37 #define ADC_CTRL_ON_STATE LOW
#define ADC_CTRL_INVERTED 1 #define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE HIGH
#endif #endif
@@ -34,7 +34,7 @@
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -53,9 +53,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 36
#define VEXT_CTRL_INVERTED 1 #define ADC_CTRL_PIN 37
#define ADC_CTRL 37 #define ADC_CTRL_ON_STATE HIGH
#define ADC_CTRL_INVERTED 0 #define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#endif #endif
@@ -34,7 +34,7 @@
// I2C // I2C
#define USE_WIRE_WITH_OLED_PINS #define USE_WIRE_WITH_OLED_PINS
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -53,10 +53,11 @@
// 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_INVERTED 1 #define ADC_CTRL_PIN 37
#define ADC_CTRL 37 #define ADC_CTRL_ON_STATE HIGH
#define ADC_CTRL_INVERTED 0 #define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
// GPS ?? // GPS ??
#define VGNS_CTRL 34 // cambiar nombre para prender GPS ? #define VGNS_CTRL 34 // cambiar nombre para prender GPS ?
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 37 #define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36 #define BOARD_I2C_SCL 36
@@ -50,9 +50,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 18 #define INTERNAL_LED_PIN 18
#define BATTERY_PIN 20 #define BATTERY_PIN 20
#define ADC_CTRL 19
#define ADC_CTRL_INVERTED 1 #define ADC_CTRL_PIN 19
#define VEXT_CTRL 45 #define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_INVERTED 1 #define VEXT_CTRL_PIN 45
#define VEXT_CTRL_ON_STATE LOW
#endif #endif
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 37 #define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36 #define BOARD_I2C_SCL 36
@@ -50,9 +50,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 18 #define INTERNAL_LED_PIN 18
#define BATTERY_PIN 20 #define BATTERY_PIN 20
#define ADC_CTRL 19
#define ADC_CTRL_INVERTED 1 #define ADC_CTRL_PIN 19
#define VEXT_CTRL 45 #define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_INVERTED 1 #define VEXT_CTRL_PIN 45
#define VEXT_CTRL_ON_STATE LOW
#endif #endif
@@ -50,9 +50,11 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define ADC_CTRL 37
#define VEXT_CTRL 36 #define ADC_CTRL_PIN 37
#define VEXT_CTRL_INVERTED 1 #define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -33,16 +33,17 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define ADC_CTRL 37
#define ADC_CTRL_INVERTED 1 #define ADC_CTRL_PIN 37
#define VEXT_CTRL 36 #define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_INVERTED 1 #define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#endif #endif
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE1_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire1
#define BOARD_I2C_SDA 41 #define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42 #define BOARD_I2C_SCL 42
@@ -44,9 +44,10 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 35 #define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define ADC_CTRL 37
#define ADC_CTRL_INVERTED 1 #define ADC_CTRL_PIN 37
#define VEXT_CTRL 36 #define ADC_CTRL_ON_STATE LOW
#define VEXT_CTRL_INVERTED 1 #define VEXT_CTRL_PIN 36
#define VEXT_CTRL_ON_STATE LOW
#endif #endif
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_14 #define GPIO_WAKEUP_PIN GPIO_SEL_14
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 7 #define BOARD_I2C_SDA 7
#define BOARD_I2C_SCL 6 #define BOARD_I2C_SCL 6
@@ -44,10 +44,11 @@
// Aditional Config // Aditional Config
#define INTERNAL_LED_PIN 18 #define INTERNAL_LED_PIN 18
#define BATTERY_PIN 1 #define BATTERY_PIN 1
#define VEXT_CTRL 3 // To turn on GPS and TFT
#define VEXT_CTRL_INVERTED 0 #define ADC_CTRL_PIN 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1
#define ADC_CTRL 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1 #define ADC_CTRL_ON_STATE HIGH
#define ADC_CTRL_INVERTED 0 #define VEXT_CTRL_PIN 3 // To turn on GPS and TFT
#define VEXT_CTRL_ON_STATE HIGH
// GPS // GPS
#define HAS_GPS #define HAS_GPS
+1 -1
View File
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_45 #define GPIO_WAKEUP_PIN GPIO_SEL_45
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 18 #define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8 #define BOARD_I2C_SCL 8
+1 -1
View File
@@ -33,7 +33,7 @@
#define GPIO_WAKEUP_PIN GPIO_SEL_45 #define GPIO_WAKEUP_PIN GPIO_SEL_45
// I2C // I2C
#define USE_WIRE_WITH_BOARD_I2C_PINS #define SENSOR_I2C_BUS Wire
#define BOARD_I2C_SDA 18 #define BOARD_I2C_SDA 18
#define BOARD_I2C_SCL 8 #define BOARD_I2C_SCL 8