LoRa_APRS_iGate/src/aprs_is_utils.cpp

375 lines
16 KiB
C++
Raw Normal View History

2023-06-06 17:30:32 +02:00
#include <WiFi.h>
#include "configuration.h"
2023-06-08 06:58:10 +02:00
#include "aprs_is_utils.h"
2023-06-08 05:55:31 +02:00
#include "station_utils.h"
2024-01-22 13:11:01 +01:00
#include "syslog_utils.h"
2023-06-08 06:58:10 +02:00
#include "query_utils.h"
2024-04-23 18:30:57 +02:00
#include "A7670_utils.h"
2024-01-12 05:36:04 +01:00
#include "digi_utils.h"
2023-06-08 06:58:10 +02:00
#include "display.h"
2023-06-09 07:12:13 +02:00
#include "utils.h"
2023-06-06 17:30:32 +02:00
2025-03-10 07:02:48 +01:00
extern Configuration Config;
extern WiFiClient espClient;
extern uint32_t lastScreenOn;
extern String firstLine;
extern String secondLine;
extern String thirdLine;
extern String fourthLine;
extern String fifthLine;
extern String sixthLine;
extern String seventhLine;
2024-04-23 18:30:57 +02:00
extern bool modemLoggedToAPRSIS;
2024-05-22 21:29:00 +02:00
extern bool backUpDigiMode;
2024-04-23 20:10:04 +02:00
2024-12-06 16:03:37 +01:00
uint32_t lastRxTime = millis();
bool passcodeValid = false;
2024-05-14 05:30:15 +02:00
2024-06-19 01:55:33 +02:00
#ifdef HAS_A7670
2024-05-11 18:59:07 +02:00
extern bool stationBeacon;
2024-04-23 18:30:57 +02:00
#endif
2023-06-06 17:30:32 +02:00
namespace APRS_IS_Utils {
2024-05-15 23:47:29 +02:00
void upload(const String& line) {
2024-02-24 14:09:05 +01:00
espClient.print(line + "\r\n");
2023-10-08 14:39:44 +02:00
}
2023-06-06 17:30:32 +02:00
2024-03-17 12:21:11 +01:00
void connect() {
2024-02-24 14:09:05 +01:00
Serial.print("Connecting to APRS-IS ... ");
uint8_t count = 0;
2024-02-24 14:09:05 +01:00
while (!espClient.connect(Config.aprs_is.server.c_str(), Config.aprs_is.port) && count < 20) {
Serial.println("Didn't connect with server...");
delay(1000);
espClient.stop();
espClient.flush();
Serial.println("Run client.stop");
Serial.println("Trying to connect with Server: " + String(Config.aprs_is.server) + " AprsServerPort: " + String(Config.aprs_is.port));
count++;
Serial.println("Try: " + String(count));
}
if (count == 20) {
Serial.println("Tried: " + String(count) + " FAILED!");
2024-12-06 16:03:37 +01:00
} else {
2024-03-17 12:21:11 +01:00
Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) + ")");
2024-03-07 17:46:38 +01:00
// String filter = "t/m/" + Config.callsign + "/" + (String)Config.aprs_is.reportingDistance;
2024-07-05 19:12:21 +02:00
String aprsAuth = "user ";
aprsAuth += Config.callsign;
aprsAuth += " pass ";
aprsAuth += Config.aprs_is.passcode;
2025-03-18 18:02:09 +01:00
aprsAuth += " vers CA2RXU_iGate 2.3 filter ";
2024-07-05 19:12:21 +02:00
aprsAuth += Config.aprs_is.filter;
upload(aprsAuth);
2024-02-24 14:09:05 +01:00
}
2023-06-06 18:37:22 +02:00
}
2024-02-24 14:09:05 +01:00
void checkStatus() {
String wifiState, aprsisState;
if (WiFi.status() == WL_CONNECTED) {
2024-03-17 12:21:11 +01:00
wifiState = "OK";
2024-04-23 18:30:57 +02:00
} else {
2024-10-08 06:03:58 +02:00
if (backUpDigiMode || Config.digi.ecoMode) {
2024-05-22 21:41:25 +02:00
wifiState = "--";
2024-05-22 21:29:00 +02:00
} else {
wifiState = "AP";
}
2024-04-29 15:19:25 +02:00
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
2024-08-14 18:32:34 +02:00
displayToggle(true);
2024-02-24 14:09:05 +01:00
}
lastScreenOn = millis();
}
2024-03-07 17:46:38 +01:00
if (!Config.aprs_is.active) {
2024-03-17 12:21:11 +01:00
aprsisState = "OFF";
2024-04-23 18:30:57 +02:00
} else {
2024-06-19 01:55:33 +02:00
#ifdef HAS_A7670
2024-05-11 18:59:07 +02:00
if (modemLoggedToAPRSIS) {
aprsisState = "OK";
} else {
aprsisState = "--";
}
2024-04-23 18:30:57 +02:00
#else
2024-05-11 18:59:07 +02:00
if (espClient.connected()) {
aprsisState = "OK";
} else {
aprsisState = "--";
}
2024-04-23 18:30:57 +02:00
#endif
2024-04-29 15:19:25 +02:00
if(aprsisState == "--" && !Config.display.alwaysOn && Config.display.timeout != 0) {
2024-08-14 18:32:34 +02:00
displayToggle(true);
2024-04-23 18:30:57 +02:00
lastScreenOn = millis();
2024-11-06 16:47:42 +01:00
}
2024-02-24 14:09:05 +01:00
}
2024-05-30 22:27:07 +02:00
secondLine = "WiFi: ";
secondLine += wifiState;
secondLine += " APRS-IS: ";
secondLine += aprsisState;
2023-06-06 18:37:22 +02:00
}
2024-06-20 20:06:14 +02:00
String checkForStartingBytes(const String& packet) {
if (packet.indexOf("\x3c\xff\x01") != -1) {
return packet.substring(0, packet.indexOf("\x3c\xff\x01"));
} else {
return packet;
2024-06-08 21:50:55 +02:00
}
2024-06-20 20:06:14 +02:00
}
String buildPacketToUpload(const String& packet) {
String buildedPacket = packet.substring(3, packet.indexOf(":"));
2024-03-07 17:46:38 +01:00
if (!(Config.aprs_is.active && Config.digi.mode == 0)) { // Check if NOT only IGate
buildedPacket += ",qAR,";
2024-06-07 06:10:04 +02:00
} else {
buildedPacket += ",qAO,";
2024-02-24 14:09:05 +01:00
}
buildedPacket += Config.callsign;
buildedPacket += checkForStartingBytes(packet.substring(packet.indexOf(":")));
return buildedPacket;
2023-10-08 14:39:44 +02:00
}
2023-06-08 03:25:31 +02:00
2024-06-28 22:05:04 +02:00
bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty) {
2024-05-15 23:47:29 +02:00
String receivedMessage;
2024-03-17 12:21:11 +01:00
if (packet.indexOf("{") > 0) { // ack?
2024-05-30 22:27:07 +02:00
String ackMessage = "ack";
ackMessage.concat(packet.substring(packet.indexOf("{") + 1));
2024-03-18 18:48:56 +01:00
ackMessage.trim();
//Serial.println(ackMessage);
String addToBuffer = Config.callsign;
2024-10-08 17:19:22 +02:00
addToBuffer += ">APLRG1";
if (!thirdParty) addToBuffer += ",RFONLY";
if (Config.beacon.path != "") {
addToBuffer += ",";
addToBuffer += Config.beacon.path;
}
addToBuffer += "::";
2024-05-15 23:47:29 +02:00
String processedSender = sender;
2024-03-17 12:21:11 +01:00
for (int i = sender.length(); i < 9; i++) {
2024-05-15 23:47:29 +02:00
processedSender += ' ';
2024-03-18 18:48:56 +01:00
}
addToBuffer += processedSender;
addToBuffer += ":";
addToBuffer += ackMessage;
STATION_Utils::addToOutputPacketBuffer(addToBuffer);
2024-03-17 12:21:11 +01:00
receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{"));
} else {
2024-03-17 12:21:11 +01:00
receivedMessage = packet.substring(packet.indexOf(":") + 1);
2024-03-18 18:48:56 +01:00
}
if (receivedMessage.indexOf("?") == 0) {
2024-04-29 15:19:25 +02:00
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
2024-08-14 18:32:34 +02:00
displayToggle(true);
2024-03-18 18:48:56 +01:00
}
2024-06-28 22:05:04 +02:00
STATION_Utils::addToOutputPacketBuffer(QUERY_Utils::process(receivedMessage, sender, false, thirdParty));
2024-03-18 18:48:56 +01:00
lastScreenOn = millis();
2024-08-14 18:32:34 +02:00
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0);
2024-03-18 18:48:56 +01:00
return true;
2024-03-17 12:21:11 +01:00
}
else {
2024-03-18 18:48:56 +01:00
return false;
}
}
2024-05-15 23:47:29 +02:00
void processLoRaPacket(const String& packet) {
2024-12-06 16:03:37 +01:00
if (passcodeValid && (espClient.connected() || modemLoggedToAPRSIS)) {
2025-03-03 15:19:25 +01:00
if (packet.indexOf("NOGATE") == -1 && packet.indexOf("RFONLY") == -1) {
int firstColonIndex = packet.indexOf(":");
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] != '}' && packet.indexOf("TCPIP") == -1) {
const String& Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
bool queryMessage = false;
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage), false);
}
if (!queryMessage) {
const String& aprsPacket = buildPacketToUpload(packet);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
2024-03-27 15:26:02 +01:00
}
2025-03-03 15:19:25 +01:00
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);
2024-02-24 14:09:05 +01:00
}
2024-11-06 16:47:42 +01:00
}
2024-03-17 12:21:11 +01:00
}
2023-10-08 14:39:44 +02:00
}
2024-02-24 14:09:05 +01:00
}
2023-06-08 05:55:31 +02:00
}
2023-06-06 21:53:06 +02:00
2024-06-24 16:32:58 +02:00
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType) {
String packet = aprsisPacket;
packet.trim();
String outputPacket = Config.callsign;
outputPacket += ">APLRG1";
if (Config.beacon.path != "") {
outputPacket += ",";
outputPacket += Config.beacon.path;
}
outputPacket += ":}";
outputPacket += packet.substring(0, packet.indexOf(",")); // Callsign>Tocall
outputPacket.concat(",TCPIP,");
outputPacket.concat(Config.callsign);
outputPacket.concat("*");
switch (packetType) {
case 0: // gps
if (packet.indexOf(":=") > 0) {
outputPacket += packet.substring(packet.indexOf(":="));
} else {
outputPacket += packet.substring(packet.indexOf(":!"));
}
break;
case 1: // messages
outputPacket += packet.substring(packet.indexOf("::"));
break;
case 2: // status
outputPacket += packet.substring(packet.indexOf(":>"));
break;
case 3: // telemetry
outputPacket += packet.substring(packet.indexOf("::"));
break;
case 4: // mic-e
if (packet.indexOf(":`") > 0) {
outputPacket += packet.substring(packet.indexOf(":`"));
} else {
outputPacket += packet.substring(packet.indexOf(":'"));
}
break;
case 5: // object
outputPacket += packet.substring(packet.indexOf(":;"));
break;
}
return outputPacket;
}
2024-05-15 23:47:29 +02:00
void processAPRSISPacket(const String& packet) {
2024-12-06 16:03:37 +01:00
if (!passcodeValid && packet.indexOf(Config.callsign) != -1) {
if (packet.indexOf("unverified") != -1 ) {
Serial.println("\n****APRS PASSCODE NOT VALID****\n");
displayShow(firstLine, "", " APRS PASSCODE", " NOT VALID !!!", "", "", "", 0);
while (1) {};
} else if (packet.indexOf("verified") != -1 ) {
passcodeValid = true;
}
}
if (passcodeValid && !packet.startsWith("#")) {
2024-06-08 18:52:47 +02:00
if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) {
String Sender = packet.substring(0, packet.indexOf(">"));
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
2024-12-06 16:03:37 +01:00
if (Addressee == Config.callsign) { // its for me!
String receivedMessage;
if (AddresseeAndMessage.indexOf("{") > 0) { // ack?
String ackMessage = "ack";
ackMessage += AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{") + 1);
ackMessage.trim();
delay(4000);
for (int i = Sender.length(); i < 9; i++) {
Sender += ' ';
2024-02-24 14:09:05 +01:00
}
String ackPacket = Config.callsign;
ackPacket += ">APLRG1,TCPIP,qAC::";
ackPacket += Sender;
ackPacket += ":";
ackPacket += ackMessage;
2024-06-19 01:55:33 +02:00
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(ackPacket);
#else
upload(ackPacket);
2024-11-06 16:47:42 +01:00
#endif
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1, AddresseeAndMessage.indexOf("{"));
2024-03-27 15:26:02 +01:00
} else {
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1);
}
if (receivedMessage.indexOf("?") == 0) {
2025-02-25 17:54:36 +01:00
Utils::println("Rx Query (APRS-IS) : " + packet);
2025-03-18 18:02:09 +01:00
Sender.trim();
2024-06-28 22:05:04 +02:00
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, true, false);
//Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n")));
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
2024-08-14 18:32:34 +02:00
displayToggle(true);
2024-02-24 14:09:05 +01:00
}
lastScreenOn = millis();
delay(500);
2024-06-19 01:55:33 +02:00
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(queryAnswer);
#else
upload(queryAnswer);
2024-09-22 18:34:13 +02:00
#endif
SYSLOG_Utils::log(2, queryAnswer, 0, 0.0, 0); // APRSIS TX
fifthLine = "APRS-IS ----> APRS-IS";
sixthLine = Config.callsign;
for (int j = sixthLine.length();j < 9;j++) {
sixthLine += " ";
}
sixthLine += "> ";
sixthLine += Sender;
seventhLine = "QUERY = ";
seventhLine += receivedMessage;
}
2025-02-28 20:48:26 +01:00
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
} else {
2025-02-25 17:54:36 +01:00
Utils::print("Rx Message (APRS-IS): " + packet);
if (STATION_Utils::wasHeard(Addressee) && packet.indexOf("EQNS.") == -1 && packet.indexOf("UNIT.") == -1 && packet.indexOf("PARM.") == -1) {
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 1));
2024-08-14 18:32:34 +02:00
displayToggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
2025-02-28 20:48:26 +01:00
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
2024-02-24 14:09:05 +01:00
}
}
2024-06-08 18:52:47 +02:00
} else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) {
2025-02-25 17:54:36 +01:00
Utils::print("Rx Object (APRS-IS) : " + packet);
if (STATION_Utils::checkObjectTime(packet)) {
2025-02-24 21:57:24 +01:00
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5));
displayToggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
2025-02-24 22:49:17 +01:00
Serial.println();
} else {
2025-02-25 17:54:36 +01:00
Serial.println(" ---> Rejected (Time): No Tx");
2025-02-24 21:57:24 +01:00
}
2024-06-07 23:29:55 +02:00
}
2023-06-09 07:12:13 +02:00
}
2023-10-08 14:39:44 +02:00
}
2023-06-09 07:12:13 +02:00
2024-03-27 15:26:02 +01:00
void listenAPRSIS() {
2024-06-19 01:55:33 +02:00
#ifdef HAS_A7670
2024-05-11 18:59:07 +02:00
A7670_Utils::listenAPRSIS();
2024-04-23 18:30:57 +02:00
#else
2024-05-11 18:59:07 +02:00
if (espClient.connected()) {
if (espClient.available()) {
String aprsisPacket = espClient.readStringUntil('\r');
2025-02-24 21:08:53 +01:00
aprsisPacket.trim(); // Serial.println(aprsisPacket);
2024-05-11 18:59:07 +02:00
processAPRSISPacket(aprsisPacket);
lastRxTime = millis();
}
2024-02-24 14:09:05 +01:00
}
2024-04-23 18:30:57 +02:00
#endif
2023-07-31 05:53:59 +02:00
}
2024-02-24 14:09:05 +01:00
2024-12-06 16:03:37 +01:00
void firstConnection() {
if (Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !espClient.connected()) {
connect();
while (!passcodeValid) {
listenAPRSIS();
}
}
}
2023-06-06 17:30:32 +02:00
}