From 61d29a5cc5f052d5992d9f0a5b5d20cb433cf345 Mon Sep 17 00:00:00 2001 From: Joerg Schultze-Lutter Date: Sat, 6 Nov 2021 21:57:50 +0100 Subject: [PATCH] New 'receive' example + bug fixes --- src/AprsLibrary.py | 23 +++--- src/receive_and_send_single_packet.robot | 94 +++++++++++++++++------- 2 files changed, 83 insertions(+), 34 deletions(-) diff --git a/src/AprsLibrary.py b/src/AprsLibrary.py index cae13c6..94edb64 100644 --- a/src/AprsLibrary.py +++ b/src/AprsLibrary.py @@ -19,7 +19,6 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # - from robot.api.deco import library, keyword from robot.api.logger import librarylogger as logger import aprslib @@ -31,7 +30,7 @@ ) logger = logging.getLogger(__name__) -__version__ = "0.3.3" +__version__ = "0.4.0" __author__ = "Joerg Schultze-Lutter" @@ -463,11 +462,14 @@ def get_msgno(self, aprs_packet): # find out if a field exists or not. @keyword("Get Value From APRS Packet") def get_value_from_aprs_packet(self, aprs_packet, field_name): - valid_message_types = [type(dict), type(str), type(byte)] - if type(aprs_packet) not in valid_message_types: - raise TypeError("This does not look like a valid APRS message type") + t_str = type("") + t_dict = type({}) + t_bytes = type(b'') - if type(aprs_packet) == t_str or type(aprs_packet) == t_byte: + if type(aprs_packet) not in [t_str, t_dict, t_bytes]: + raise TypeError(f"This packet does not look like a valid APRS message type: {type(aprs_packet)}") + + if type(aprs_packet) == t_str or type(aprs_packet) == t_bytes: packet = self.parse_aprs_packet(aprs_packet=aprs_packet) if type(packet) == t_dict: if field_name in packet: @@ -545,11 +547,14 @@ def check_packet_msgno(self, aprs_packet): # raw format (str or bytes) OR decoded. @keyword("Check If APRS Packet Contains") def check_if_field_exists_in_packet(self, aprs_packet, field_name): - valid_message_types = [type(dict), type(str), type(byte)] - if type(aprs_packet) not in valid_message_types: + t_str = type("") + t_dict = type({}) + t_bytes = type(b'') + + if type(aprs_packet) not in [t_str, t_dict, t_bytes]: raise TypeError("This does not look like a valid APRS message type") - if type(aprs_packet) == t_str or type(aprs_packet) == t_byte: + if type(aprs_packet) == t_str or type(aprs_packet) == t_bytes: packet = self.parse_aprs_packet(aprs_packet=aprs_packet) if type(packet) == t_dict: return True if field_name in packet else False diff --git a/src/receive_and_send_single_packet.robot b/src/receive_and_send_single_packet.robot index ecc9192..3c662cf 100644 --- a/src/receive_and_send_single_packet.robot +++ b/src/receive_and_send_single_packet.robot @@ -23,39 +23,43 @@ ${filter} g/${callsign}* *** Test Cases *** Simple Receive-and-Respond Test Case [Documentation] Our 'master receiver' task - # The current Robot Framework does not support WHILE loops. This is a still a + # Robot Framework 4.x does not support WHILE loops. This is a still a # finite loop but as our goal is only to receive a single message, this - # crude approach will do. - Wait Until Keyword Succeeds 50x 0sec Receive Packet From APRS-IS + # crude approach will do. Keep in mind that by default, the APRSLib is + # queried in "blocked" mode, meaning that we don't need any retries etc. + # + # The current setup will accept up to 10 messages, confirm them whereas + # necessary and send a pesonalized response. After processing these 10 + # messages, the test will stop its execution + Wait Until Keyword Succeeds 10x 0sec Receive Packet From APRS-IS *** Keywords *** Receive packet from APRS-IS [Documentation] VERY simplified ack-and-respond-to-message test case. Sends ack & msg to user, then terminates the test + + # Get the packet from APRS-IS Log Receive message from APRS-IS ${packet} = Receive APRS Packet + Log To Console Receive complete + + # check what we have received so far ${format_string}= Get Format Value From APRS Packet ${packet} - Run Keyword If '${format_string}' != 'message' Fail msg=Packet format is not 'message'; start new loop - - ${from_string}= Get From Value From APRS Packet ${packet} - ${adresse_string}= Get Adresse Value From APRS Packet ${packet} - ${msgtext_string}= Get Message Text Value From APRS Packet ${packet} - # The msgno might not be present for unconfirmed messsages. A failure to extract the msgno - # simply triggers a new WUKS loop. After all, this is a VERY very simplified library demo. - # - # Therefore, I don't care about this case and simply expect to receive a message with a - # msgno present. Additionally, keep in mind that alphanumeric message number qualifiers - # are currently not parsed by the aprslib library. - ${msgno_string}= Get Message Number Value From APRS Packet ${packet} + # and handle response/message formats + Run Keyword If '${format_string}' == 'response' Process APRS Response MYPACKET=${packet} + Run Keyword If '${format_string}' == 'message' Process APRS Message MYPACKET=${packet} - # If we have received an ack or a rej, we simply ignore the message and start anew - Run Keyword If '${msgtext_string}' == 'ack' Fail msg=Ignoring ack, start new loop - Run Keyword If '${msgtext_string}' == 'rej' Fail msg=Ignoring rej, start new loop + Log To Console And we're done - # show the user what we have received - Log To Console I have received '${msgtext_string}' +Send Acknowledgment + [Documentation] Send an acknowledgement in case the incoming message + [Arguments] ${MYPACKET} + + ${from_string}= Get From Value From APRS Packet ${MYPACKET} + ${adresse_string}= Get Adresse Value From APRS Packet ${MYPACKET} + ${msgno_string}= Get Message Number Value From APRS Packet ${MYPACKET} # Send the ack # build the ack based on the incoming message number @@ -65,21 +69,61 @@ Receive packet from APRS-IS Send Packet to APRS-IS ${ackmsg} # do not flood the APRS-IS network - Sleep 2sec + Log To Console Sleep 5 secs + Sleep 5sec + +Process APRS Message + [Documentation] Process an APRS Message (format type: 'messsage') + [Arguments] ${MYPACKET} + + Log To Console Processing an APRS 'message' packet + + # show the user what we have received + Log To Console I have received '${MYPACKET}' from APRS-IS - # Send the actual message + # Send an acknowledgment in case we have received a message containing a message number + ${msgno_present}= Check If APRS Packet Contains Message Number ${MYPACKET} + Log To Console Message contains a message number: ${msgno_present} + + Run Keyword If '${msgno_present}' == '${True}' Send Acknowledgment MYPACKET=${MYPACKET} + + # Extract some fields from the original message + ${from_string}= Get From Value From APRS Packet ${MYPACKET} + ${adresse_string}= Get Adresse Value From APRS Packet ${MYPACKET} + + # Send the response message # Get a message number from the library ${mymsgno}= Get APRS MsgNo As Alphanumeric Value + # Increment the library's message number (not really necessary here as we only deal with one message) Increment APRS MsgNo + # build the final string ${msg}= Format String {}>APRS::{:9}:{} {}{} ${adresse_string} ${from_string} Hello ${from_string} , your Robot Overlords send greetings! - ${msg}= Catenate SEPARATOR= ${msg} { ${mymsgno} + + # our response will always contain a message number, even though the incoming message had none + # Remember that this is just a simple demo script + ${msg}= Catenate SEPARATOR= ${msg} { ${mymsgno} + # and send the message to APRS-IS - Log To Console Sending actual message '${msg}' + Log To Console Sending response message '${msg}' to APRS-IS Send Packet to APRS-IS ${msg} - Log To Console And we're done + # Since we do not intentionally fail this command sequence, we will automatically break free from the encapsulating WUKS + Log To Console Process APRS Message complete. + +Process APRS Response + [Documentation] Process an APRS Response (format type: 'response'). Causes a desired fail (thus causing another WUKS loop) in case an ack/rej has been received + [Arguments] ${MYPACKET} + + # At this point, we already know that there is a response present. Normally, this can only be an ack or a rej + # but let's be sure about that and check the value + ${response_string} Get Response Value from APRS Packet ${MYPACKET} + + # If we have received an ack or a rej, we simply ignore the message and start anew + Run Keyword If '${response_string}' == 'ack' Fail msg=Ignoring ack, start new loop + Run Keyword If '${response_string}' == 'rej' Fail msg=Ignoring rej, start new loop + Send Packet to APRS-IS [Documentation] Send packet to APRS-IS