diff --git a/include/aprs_is_utils.h b/include/aprs_is_utils.h index 8e05e3b..bd0b978 100644 --- a/include/aprs_is_utils.h +++ b/include/aprs_is_utils.h @@ -35,11 +35,16 @@ namespace APRS_IS_Utils { void processLoRaPacket(const String& packet); String buildPacketToTx(const String& aprsisPacket, uint8_t packetType); - void processAPRSISPacket(const String& packet); + void processAPRSISPacket();//const String& packet); void listenAPRSIS(); void firstConnection(); + bool startListenerAPRSISTask(uint32_t stackSize = 8192, UBaseType_t priority = 1); + void stopListenerAPRSISTask(); + void suspendListenerAPRSISTask(); + void resumeListenerAPRSISTask(); + } #endif \ No newline at end of file diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 7a24794..6482fa4 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -96,6 +96,11 @@ std::vector receivedPackets; String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine; //#define STARTUP_DELAY 5 //min +#ifdef HAS_TWO_CORES + QueueHandle_t aprsIsTxQueue = NULL; + QueueHandle_t aprsIsRxQueue = NULL; +#endif + void setup() { Serial.begin(115200); @@ -122,11 +127,39 @@ void setup() { A7670_Utils::setup(); #endif Utils::checkRebootMode(); + APRS_IS_Utils::firstConnection(); SLEEP_Utils::checkSerial(); + + // Crear queues con verificación detallada + //Serial.println("Creando aprsIsTxQueue..."); + aprsIsTxQueue = xQueueCreate(50, sizeof(String)); + //Serial.printf("aprsIsTxQueue = %p\n", aprsIsTxQueue); + + //Serial.println("Creando aprsIsRxQueue..."); + aprsIsRxQueue = xQueueCreate(50, sizeof(String)); + //Serial.printf("aprsIsRxQueue = %p\n", aprsIsRxQueue); + + // Verificación crítica + if (aprsIsRxQueue == NULL || aprsIsTxQueue == NULL) { + Serial.println("FATAL: Error creando queues!"); + while(1) { + Serial.println("STUCK - Queues failed"); + delay(1000); + } + } + Serial.println("Queues creadas OK"); + + // Iniciar el task de APRSIS + if (!APRS_IS_Utils::startListenerAPRSISTask()) { + Serial.println("Error: No se pudo crear el task de APRSIS"); + } } void loop() { + //Serial.println("Loop tick: " + String(millis())); + //delay(1000); + if (Config.digi.ecoMode == 1) { SLEEP_Utils::checkWakeUpFlag(); Utils::checkBeaconInterval(); @@ -201,7 +234,8 @@ void loop() { } if (Config.aprs_is.active) { - APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS + APRS_IS_Utils::processAPRSISPacket(); + //APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS } STATION_Utils::processOutputPacketBuffer(); diff --git a/src/aprs_is_utils.cpp b/src/aprs_is_utils.cpp index cddad0f..94b9e68 100644 --- a/src/aprs_is_utils.cpp +++ b/src/aprs_is_utils.cpp @@ -31,6 +31,7 @@ extern Configuration Config; extern WiFiClient espClient; +extern QueueHandle_t aprsIsRxQueue; extern uint32_t lastScreenOn; extern String firstLine; extern String secondLine; @@ -52,6 +53,9 @@ bool passcodeValid = false; namespace APRS_IS_Utils { + // Handle del task (opcional, para poder controlarlo después) + TaskHandle_t aprsisTaskHandle = NULL; + void upload(const String& line) { espClient.print(line + "\r\n"); } @@ -274,95 +278,103 @@ namespace APRS_IS_Utils { return outputPacket; } - void processAPRSISPacket(const String& packet) { - 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("#")) { - 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 += ' '; - } + //uint32_t lastLog = 0; + void processAPRSISPacket() { + /*Serial.println("processAPRSISPacket"); - 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("{")); + if (millis() - lastLog > 5000) { // Cada 5 segundos + UBaseType_t packets = uxQueueMessagesWaiting(aprsIsRxQueue); + UBaseType_t spaces = uxQueueSpacesAvailable(aprsIsRxQueue); + Serial.printf("[STATS] APRSIS Queue: %d/%d (%.1f%% full)\n", + packets, packets + spaces, + (packets * 100.0) / (packets + spaces)); + lastLog = millis(); + }*/ + + + String packet; + if (xQueueReceive(aprsIsRxQueue, &packet, 0) == pdTRUE) { + + if (passcodeValid && !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("Rx Query (APRS-IS) : " + packet); + Sender.trim(); + 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; + } + displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); } else { - receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1); - } - if (receivedMessage.indexOf("?") == 0) { - Utils::println("Rx Query (APRS-IS) : " + packet); - Sender.trim(); - 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) { + 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)); displayToggle(true); + lastScreenOn = millis(); + Utils::typeOfPacket(packet, 1); // APRS-LoRa + displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); } - 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; } - displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); - } else { - 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)); + } else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) { + Utils::print("Rx Object (APRS-IS) : " + packet); + if (STATION_Utils::checkObjectTime(packet)) { + STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5)); displayToggle(true); lastScreenOn = millis(); Utils::typeOfPacket(packet, 1); // APRS-LoRa - displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); + Serial.println(); + } else { + Serial.println(" ---> Rejected (Time): No Tx"); } } - } else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) { - Utils::print("Rx Object (APRS-IS) : " + packet); - if (STATION_Utils::checkObjectTime(packet)) { - STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5)); - displayToggle(true); - lastScreenOn = millis(); - Utils::typeOfPacket(packet, 1); // APRS-LoRa - Serial.println(); - } else { - Serial.println(" ---> Rejected (Time): No Tx"); - } } } } @@ -374,8 +386,9 @@ namespace APRS_IS_Utils { if (espClient.connected()) { if (espClient.available()) { String aprsisPacket = espClient.readStringUntil('\r'); - aprsisPacket.trim(); // Serial.println(aprsisPacket); - processAPRSISPacket(aprsisPacket); + aprsisPacket.trim(); //Serial.println(aprsisPacket); + xQueueSend(aprsIsRxQueue, &aprsisPacket, 0); + //processAPRSISPacket(aprsisPacket); lastRxTime = millis(); } } @@ -386,9 +399,65 @@ namespace APRS_IS_Utils { if (Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !espClient.connected()) { connect(); while (!passcodeValid) { - listenAPRSIS(); + if (espClient.connected() && espClient.available()) { + String aprsisPacket = espClient.readStringUntil('\r'); + aprsisPacket.trim(); + if (!passcodeValid && aprsisPacket.indexOf(Config.callsign) != -1) { + if (aprsisPacket.indexOf("unverified") != -1 ) { + Serial.println("\n****APRS PASSCODE NOT VALID****\n"); + displayShow(firstLine, "", " APRS PASSCODE", " NOT VALID !!!", "", "", "", 0); + while (1) {}; + } else if (aprsisPacket.indexOf("verified") != -1 ) { + Serial.println("(APRS PASSCODE VALIDATED)"); + passcodeValid = true; + } + } + } } } } + + void aprsisListenerTask(void *parameter) { + while (true) { + listenAPRSIS(); + vTaskDelay(pdMS_TO_TICKS(10)); // 10ms delay + } + } + + // Función para iniciar el task + bool startListenerAPRSISTask(uint32_t stackSize, UBaseType_t priority) { + BaseType_t result = xTaskCreatePinnedToCore( + aprsisListenerTask, // Función del task + "APRSIS_Listener", // Nombre del task + stackSize, // Stack size en words (no bytes) + NULL, // Parámetro pasado al task + priority, // Prioridad + &aprsisTaskHandle, // Handle del task + 0 + ); + + return (result == pdPASS); + } + + // Función opcional para detener el task + void stopListenerAPRSISTask() { + if (aprsisTaskHandle != NULL) { + vTaskDelete(aprsisTaskHandle); + aprsisTaskHandle = NULL; + } + } + + // Función opcional para suspender/reanudar el task + void suspendListenerAPRSISTask() { + if (aprsisTaskHandle != NULL) { + vTaskSuspend(aprsisTaskHandle); + } + } + + void resumeListenerAPRSISTask() { + if (aprsisTaskHandle != NULL) { + vTaskResume(aprsisTaskHandle); + } + } } \ No newline at end of file diff --git a/src/display.cpp b/src/display.cpp index e304311..1dc47ab 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -101,7 +101,8 @@ void displaySetup() { #endif #if defined(TTGO_T_Beam_S3_SUPREME_V3) - if (!display.begin(0x3c, false)) { + if (!display.begin(0x3c)) { + //if (!display.begin(0x3c, false)) { displayFound = true; if (Config.display.turn180) display.setRotation(2); display.clearDisplay(); diff --git a/variants/ttgo-lora32-v21/board_pinout.h b/variants/ttgo-lora32-v21/board_pinout.h index 80ebd7c..bd4c68c 100644 --- a/variants/ttgo-lora32-v21/board_pinout.h +++ b/variants/ttgo-lora32-v21/board_pinout.h @@ -42,6 +42,7 @@ #define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin) // Aditional Config + #define HAS_TWO_CORES #define INTERNAL_LED_PIN 25 // Green Led #define BATTERY_PIN 35 #define HAS_ADC_CALIBRATION