#include #include "configuration.h" #include "aprs_is_utils.h" #include "station_utils.h" #include "syslog_utils.h" #include "query_utils.h" #include "A7670_utils.h" #include "digi_utils.h" #include "display.h" #include "utils.h" 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; extern bool modemLoggedToAPRSIS; extern bool backUpDigiMode; uint32_t lastRxTime = millis(); #ifdef HAS_A7670 extern bool stationBeacon; #endif namespace APRS_IS_Utils { void upload(const String& line) { espClient.print(line + "\r\n"); } void connect() { Serial.print("Connecting to APRS-IS ... "); uint8_t count = 0; 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!"); } else { Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) + ")"); // String filter = "t/m/" + Config.callsign + "/" + (String)Config.aprs_is.reportingDistance; String aprsAuth = "user "; aprsAuth += Config.callsign; aprsAuth += " pass "; aprsAuth += Config.aprs_is.passcode; aprsAuth += " vers CA2RXU_LoRa_iGate 1.4 filter "; aprsAuth += Config.aprs_is.filter; upload(aprsAuth); delay(200); } } void checkStatus() { String wifiState, aprsisState; if (WiFi.status() == WL_CONNECTED) { wifiState = "OK"; } else { if (backUpDigiMode) { wifiState = "--"; } else { wifiState = "AP"; } if (!Config.display.alwaysOn && Config.display.timeout != 0) { displayToggle(true); } lastScreenOn = millis(); } if (!Config.aprs_is.active) { aprsisState = "OFF"; } else { #ifdef HAS_A7670 if (modemLoggedToAPRSIS) { aprsisState = "OK"; } else { aprsisState = "--"; } #else if (espClient.connected()) { aprsisState = "OK"; } else { aprsisState = "--"; } #endif if(aprsisState == "--" && !Config.display.alwaysOn && Config.display.timeout != 0) { displayToggle(true); lastScreenOn = millis(); } } secondLine = "WiFi: "; secondLine += wifiState; secondLine += " APRS-IS: "; secondLine += aprsisState; } String checkForStartingBytes(const String& packet) { if (packet.indexOf("\x3c\xff\x01") != -1) { return packet.substring(0, packet.indexOf("\x3c\xff\x01")); } else { return packet; } } String buildPacketToUpload(const String& packet) { String buildedPacket = packet.substring(3, packet.indexOf(":")); if (!(Config.aprs_is.active && Config.digi.mode == 0)) { // Check if NOT only IGate buildedPacket += ",qAR,"; } else { buildedPacket += ",qAO,"; } buildedPacket += Config.callsign; buildedPacket += checkForStartingBytes(packet.substring(packet.indexOf(":"))); return buildedPacket; } bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty) { String receivedMessage; if (packet.indexOf("{") > 0) { // ack? String ackMessage = "ack"; ackMessage.concat(packet.substring(packet.indexOf("{") + 1)); ackMessage.trim(); //Serial.println(ackMessage); String addToBuffer = Config.callsign; addToBuffer += ">APLRG1,RFONLY"; if (Config.beacon.path != "") { addToBuffer += ","; addToBuffer += Config.beacon.path; } addToBuffer += "::"; String processedSender = sender; for (int i = sender.length(); i < 9; i++) { processedSender += ' '; } addToBuffer += processedSender; addToBuffer += ":"; addToBuffer += ackMessage; STATION_Utils::addToOutputPacketBuffer(addToBuffer); receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{")); } else { receivedMessage = packet.substring(packet.indexOf(":") + 1); } if (receivedMessage.indexOf("?") == 0) { if (!Config.display.alwaysOn && Config.display.timeout != 0) { displayToggle(true); } STATION_Utils::addToOutputPacketBuffer(QUERY_Utils::process(receivedMessage, sender, false, thirdParty)); lastScreenOn = millis(); displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0); return true; } else { return false; } } void processLoRaPacket(const String& packet) { if (espClient.connected() || modemLoggedToAPRSIS) { if (packet != "") { if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) { int firstColonIndex = packet.indexOf(":"); if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] != '}' && packet.indexOf("TCPIP") == -1) { const String& Sender = packet.substring(3, packet.indexOf(">")); if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) { STATION_Utils::updateLastHeard(Sender); Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2); String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); Addressee.trim(); bool queryMessage = false; if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me! queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage), false); } if (!queryMessage) { const String& aprsPacket = buildPacketToUpload(packet); if (!Config.display.alwaysOn && Config.display.timeout != 0) { 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); } } } } } } } 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; } void processAPRSISPacket(const String& packet) { if (!packet.startsWith("#")) { 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(); 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 += ' '; } String ackPacket = Config.callsign; ackPacket += ">APLRG1,TCPIP,qAC::"; ackPacket += Sender; ackPacket += ":"; ackPacket += ackMessage; #ifdef HAS_A7670 A7670_Utils::uploadToAPRSIS(ackPacket); #else upload(ackPacket); #endif receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1, AddresseeAndMessage.indexOf("{")); } else { receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1); } if (receivedMessage.indexOf("?") == 0) { Utils::println("Received Query APRS-IS : " + packet); 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) { displayToggle(true); } lastScreenOn = millis(); delay(500); #ifdef HAS_A7670 A7670_Utils::uploadToAPRSIS(queryAnswer); #else upload(queryAnswer); #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; } } else { Utils::print("Received Message from APRS-IS : " + packet); if (STATION_Utils::wasHeard(Addressee)) { STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 1)); displayToggle(true); lastScreenOn = millis(); Utils::typeOfPacket(packet, 1); // APRS-LoRa } } displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); } else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) { Utils::println("Received Object from APRS-IS : " + packet); STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5)); displayToggle(true); lastScreenOn = millis(); Utils::typeOfPacket(packet, 1); // APRS-LoRa } } } void listenAPRSIS() { #ifdef HAS_A7670 A7670_Utils::listenAPRSIS(); #else if (espClient.connected()) { if (espClient.available()) { String aprsisPacket = espClient.readStringUntil('\r'); // Serial.println(aprsisPacket); processAPRSISPacket(aprsisPacket); lastRxTime = millis(); } } #endif } }