diff --git a/examples/APRS/APRS_Position/APRS_Position.ino b/examples/APRS/APRS_Position/APRS_Position.ino index e18804846..cf7f6977e 100644 --- a/examples/APRS/APRS_Position/APRS_Position.ino +++ b/examples/APRS/APRS_Position/APRS_Position.ino @@ -109,32 +109,49 @@ void setup() { } void loop() { - Serial.print(F("[APRS] Sending position ... ")); + Serial.println(F("[APRS] Sending location reports")); // send a location without message or timestamp char destination[] = "N0CALL"; char latitude[] = "4911.67N"; char longitude[] = "01635.96E"; int state = aprs.sendPosition(destination, 0, latitude, longitude); + if(state != RADIOLIB_ERR_NONE) { + Serial.print(F("[APRS] Failed to send location, code ")); + Serial.println(state); + } delay(500); // send a location with message and without timestamp char message[] = "I'm here!"; - state |= aprs.sendPosition(destination, 0, latitude, longitude, message); + state = aprs.sendPosition(destination, 0, latitude, longitude, message); + if(state != RADIOLIB_ERR_NONE) { + Serial.print(F("[APRS] Failed to send location and message code ")); + Serial.println(state); + } delay(500); + + // you can also set repeater callsigns and SSIDs + // up to 8 repeaters may be used + // sendPosition will be sent with "WIDE2-2" path + char* repeaterCallsigns[] = { "WIDE2" }; + uint8_t repeaterSSIDs[] = { 2 }; + aprs.useRepeaters(repeaterCallsigns, repeaterSSIDs, 1); // send a location with message and timestamp char timestamp[] = "093045z"; - state |= aprs.sendPosition(destination, 0, latitude, longitude, message, timestamp); - delay(500); - - if(state == RADIOLIB_ERR_NONE) { - Serial.println(F("success!")); - } else { - Serial.print(F("failed, code ")); + state = aprs.sendPosition(destination, 0, latitude, longitude, message, timestamp); + if(state != RADIOLIB_ERR_NONE) { + Serial.print(F("[APRS] Failed to send location, message and timestamp code ")); Serial.println(state); } + delay(500); + + // when repeaters are no longer needed, they can be dropped + aprs.dropRepeaters(); // wait one minute before transmitting again + Serial.println(F("[APRS] All done!")); delay(60000); } + diff --git a/keywords.txt b/keywords.txt index 273fd409c..d903819b7 100644 --- a/keywords.txt +++ b/keywords.txt @@ -313,6 +313,8 @@ noTone KEYWORD2 # APRS sendPosition KEYWORD2 sendMicE KEYWORD2 +useRepeaters KEYWORD2 +dropRepeaters KEYWORD2 # Pager sendTone KEYWORD2 diff --git a/src/protocols/APRS/APRS.cpp b/src/protocols/APRS/APRS.cpp index a5866ac61..c2fb72f3e 100644 --- a/src/protocols/APRS/APRS.cpp +++ b/src/protocols/APRS/APRS.cpp @@ -260,6 +260,12 @@ int16_t APRSClient::sendFrame(char* destCallsign, uint8_t destSSID, char* info) RADIOLIB_AX25_CONTROL_UNNUMBERED_FRAME, RADIOLIB_AX25_PID_NO_LAYER_3, const_cast(info)); + // optionally set repeaters + if(this->repCalls && this->repSSIDs && this->numReps) { + int16_t state = frameUI.setRepeaters(this->repCalls, this->repSSIDs, this->numReps); + RADIOLIB_ASSERT(state); + } + return(axClient->sendFrame(&frameUI)); } else if(this->phyLayer != nullptr) { @@ -276,4 +282,16 @@ int16_t APRSClient::sendFrame(char* destCallsign, uint8_t destSSID, char* info) return(RADIOLIB_ERR_WRONG_MODEM); } +void APRSClient::useRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters) { + this->repCalls = repeaterCallsigns; + this->repSSIDs = repeaterSSIDs; + this->numReps = numRepeaters; +} + +void APRSClient::dropRepeaters() { + this->repCalls = NULL; + this->repSSIDs = NULL; + this->numReps = 0; +} + #endif diff --git a/src/protocols/APRS/APRS.h b/src/protocols/APRS/APRS.h index 7b14ad889..44031fdea 100644 --- a/src/protocols/APRS/APRS.h +++ b/src/protocols/APRS/APRS.h @@ -144,6 +144,21 @@ class APRSClient { */ int16_t sendFrame(char* destCallsign, uint8_t destSSID, char* info); + /*! + \brief Set the repeater callsigns and SSIDs to be used by the frames sent by sendPosition, sendMicE or sendFrame. + \param repeaterCallsigns Array of repeater callsigns in the form of null-terminated C-strings. + \param repeaterSSIDs Array of repeater SSIDs. + \param numRepeaters Number of repeaters, maximum is 8. + \returns \ref status_codes + */ + void useRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters); + + /*! + \brief Stop using repeaters. + \returns \ref status_codes + */ + void dropRepeaters(); + #if !RADIOLIB_GODMODE private: #endif @@ -153,6 +168,11 @@ class APRSClient { // default APRS symbol (car) char symbol = '>'; char table = '/'; + + // repeaters + char** repCalls = NULL; + uint8_t* repSSIDs = NULL; + uint8_t numReps = 0; // source callsign when using APRS over LoRa char src[RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1] = { 0 };