Skip to content

Building an Application

Now that you've got your station set up, it's time to build an application!

We're going to start with a very simple 'Hello World!' application. This application will listen for packets addressed to it, and respond with 'Hello World!' before disconnecting.

Creating the Application

To create the application, we need to subclass the provided Application base class. We'll create a new file named hello.py in the same directory as our main.py and call our application HelloWorld:

hello.py
from pax25 import Application
from pax25.applications.utils import send_message


class HelloWorld(Application):
    """
    My first application!
    """

    def on_startup(self, connection):
        """
        This method is called when the user first connects.
        """

        send_message(connection, "Hello World!")
        connection.disconnect()

Now, in our original main.py, we'll remove the BulletinBoard import and replace it with our new HelloWorld application:

main.py
# At the top, add:
from hello import HelloWorld

...

# Here's our old line:
# station.register_app(BulletinBoard, interfaces=["file"], settings={})
# And here's our new one:
station.connection.add_app(HelloWorld, interfaces=["file"], settings={})

Now, when we run our station, we'll see our new application in action!

$ python main.py
Hello World!

The application will then disconnect and we'll close.

Adding Complexity

A 'Hello World!' application is all well and good, but it's not very useful. Let's add some complexity to our application. The classic game of high-low is a good example of a simple application that can be built on top of Pax25.

Let's create a new application called HighLow:

high_low.py
import random

from pax25 import Application
from pax25.applications.utils import send_message


class HighLow(Application):
    """
    A simple game of high-low.
    """

    def setup(self):
        """
        This method is called when the application is registered with the station.

        We set up any basic state scaffolding here.
        """
        self.games = {}

    def on_startup(self, connection):
        """
        This method is called when the user first connects.
        """
        send_message(connection, "[HiLow-0.0.1]")  # (1)
        send_message(connection, "Welcome to High-Low!") # (2)
        # Start our first game.
        self.new_game(connection)

    def new_game(self, connection):
       """
       Start a new game.
       """
       # Multiple connections could be talking to our station at once.
       # We need to keep track of which connection is playing which game.
       #
       # Connections can be used as keys for tracking this sort of thing.
       self.games[connection] = {
          "number": random.randint(1, 100),
          "guesses": 0,
       }
       send_message(
          connection,
          "I've picked a number between 1 and 100.\r"
          + "Try to guess it, or type 'quit' to quit!"  # (3)
       )
       send_message(connection, "Try to guess it, or type 'quit' to quit!")

    def handle_guess(self, connection, guess):
        """
        This method is called when the user sends a guess.
        """
        # First, let's increase the number of guesses the user has made.
        self.games[connection]["guesses"] += 1
        # If the user's guess is too high, tell them.
        if guess > self.games[connection]["number"]:
            send_message(connection, "Too high!")
        # If the user's guess is too low, tell them.
        elif guess < self.games[connection]["number"]:
            send_message(connection, "Too low!")
        # If the user's guess is correct, tell them and start a new game.
        else:
            guesses = self.games[connection]["guesses"]
            send_message(connection, f"You got it in {guesses}!")
            self.new_game(connection)

    def on_message(self, connection, message):
        """
        This method is called when the user sends a message.
        """
        # The user has two options-- they can send a guess, or they can quit.
        if message == "quit":
            send_message(connection, "Thanks for playing!")
            connection.disconnect()
            return
        # Try to convert the message to an integer.
        try:
            guess = int(message)
        except ValueError:
            send_message(connection, "That's not a number!")
            return
        self.handle_guess(connection, guess)

    def on_shutdown(self, connection):
       """
       This method is called when the user disconnects.
       """
       # Let's clean up after ourselves and remove the user's game
       # now that they're leaving.
       del self.games[connection]
  1. You should always make the first line you send from your application a version string containing a short name and a version number. This is so that clients can identify your application and know what to expect.

    A proper version string should start and end with a square bracket. The name and version number should be separated by a dash. The version number should be in the format MAJOR.MINOR.PATCH. For example, "[HelloWorld-1.0.0]". We recommend using semantic versioning.

  2. We've used two back-to-back send_message statements here. You may want to construct the full message you want to send and only do one send_message call-- especially if you're sending a lot of text at once. Each send message call requires the creation of at least one packet, and that can be expensive. In the future, such calls may be optimized to automatically combine packets.

  3. This time, we combine the strings. Pax25 will automatically break up long strings into multiple packets for us, so we don't have to worry about one string being too long. Also note that the line break character is \r in packet radio, rather than \n or \r\n as is seen in modern Windows and UNIX/Linux systems.

Replacing HelloWorld with HighLow in main.py, we can now play a game of high-low!

$ python main.py
Welcome to High-Low!
I've picked a number between 1 and 100.
Try to guess it, or type 'quit' to quit!
50
Too low!
75
Too high!
62
Too low!
68
Too high!
65
Too high!
64
Too high!
63
You got it in 7!
I've picked a number between 1 and 100.
Try to guess it, or type 'quit' to quit!
quit
Thanks for playing!

Next Steps

Now that you've built some simple applications, you'll want to read over the Application documentation to learn about all the methods you can override to build more complex applications.