Table of Contents
Creating a simple BPQ Application
This tutorial shows you how to set up a simple python script connected to linbpq as a telnet application.
In order to do this we'll do the following:
- Create a location for the script, data, and a python
venv
- Write the script
- Add the application to
BPQ32.cfg
- Setup a
systemd
service to keep it running.
Setup
To organize this project, I created a python virtual environment called bpq-apps
in my .local
directory, and installed the telnetlib3
module that it depends on. Within the bpq-apps
virtual environment directory, I also created a folder called scripts and a folder called data. I'm going to install various small BPQ applications here.
I'm using the python virtual environment framework to help manage the various dependencies I might want to use for these scripts.
$ cd ~/.local $ python -m venv bpq-apps $ cd ./bpq-apps $ mkdir scripts data $ source ./bin/activate (bpq-apps)$ pip install telnetlib3
Writing the program
I chose to write this in Python to be a little more clear than the Perl application provided in the link above.
The BPQ Application, called ROLL
uses a file called messages.json
to provide it a welcome message and the blocks of text. The script itself was placed under the scripts
directory created above, saved as rick.py
Program Code
This program was adapted from the example for the ''telnetlib3'' Python module
import asyncio, telnetlib3, json from optparse import OptionParser parser = OptionParser() parser.add_option("-f", "--file", dest="filename", help="which json file with message and welcome", metavar="FILE") parser.add_option("-p", "--port", dest="port", help="on which port?", metavar="PORT") (options, args) = parser.parse_args() messages = json.load(open(options.filename,'r')) async def shell(reader, writer): incall = await reader.readline() print("%s connected" % incall) writer.write("\r\nWelcome %s" % incall) writer.write("\r\n%s" % messages["welcome"]) textblocks = messages["text"].copy() leave = False #inp[0].upper() in ["Q", "B"] rolled = False inp = await reader.read(1) while inp and not leave and len(textblocks) > 0: print("writing next block") writer.write(textblocks.pop(0)) await writer.drain() inp = await reader.readline() if not rolled: print("%s rickrolled" % incall) rolled = True leave = inp[0].upper() in ["Q", "B"] and rolled writer.close() loop = asyncio.get_event_loop() coro = telnetlib3.create_server(port=options.port, shell=shell) server = loop.run_until_complete(coro) loop.run_until_complete(server.wait_closed())
''messages.json'' file
{ "welcome": "We're no strangers to love\r\nYou know the rules and so do I (Do I)\r\nA full commitment's what I'm thinking of\r\nYou wouldn't get this from any other guy\r\nI just wanna tell you how I'm feeling\r\nGotta make you understand\r\n", "text": ["Never gonna give you up\r\nNever gonna let you down\r\nNever gonna run around and desert you\r\nNever gonna make you cry\r\nNever gonna say goodbye\r\nNever gonna tell a lie and hurt you\r\n", "\r\nWe've known each other for so long\r\nYour heart's been aching, but you're too shy to say it (To say it)\r\nInside, we both know what's been going on (Going on)\r\nWe know the game, and we're gonna play it\r\n\r\nAnd if you ask me how I'm feeling\r\nDon't tell me you're too blind to see\r\n", "\r\nNever gonna give you up\r\nNever gonna let you down\r\nNever gonna run around and desert you\r\nNever gonna make you cry\r\nNever gonna say goodbye\r\nNever gonna tell a lie and hurt you\r\n", "\r\nNever gonna give you up\r\nNever gonna let you down\r\nNever gonna run around and desert you\r\nNever gonna make you cry\r\nNever gonna say goodbye\r\nNever gonna tell a lie and hurt you\r\n", "\r\nOoh (Give you up)\r\nOoh-ooh (Give you up)\r\nOoh-ooh\r\nNever gonna give, never gonna give (Give you up)\r\nOoh-ooh\r\nNever gonna give, never gonna give (Give you up)\r\n\r\nWe've known each other for so long\r\nYour heart's been aching, but you're too shy to say it (To say it)\r\n", "\r\nInside, we both know what's been going on (Going on)\r\nWe know the game, and we're gonna play it\r\n\r\nI just wanna tell you how I'm feeling\r\nGotta make you understand\r\n", "\r\nNever gonna give you up\r\nNever gonna let you down\r\nNever gonna run around and desert you\r\nNever gonna make you cry\r\nNever gonna say goodbye\r\nNever gonna tell a lie and hurt you\r\n", "\r\nNever gonna give you up\r\nNever gonna let you down\r\nNever gonna run around and desert you\r\nNever gonna make you cry\r\nNever gonna say goodbye\r\nNever gonna tell a lie and hurt you\r\n", "\r\nNever gonna give you up\r\nNever gonna let you down\r\nNever gonna run around and desert you\r\nNever gonna make you cry\r\nNever gonna say goodbye\r\nNever gonna tell a lie and hurt you\r\n" ] }
BPQ configuration
In my bpq32.cfg
file, I added the port number to the telnet port, where the fourth entry, 10001
is the port for my new application:
CMDPORT=8005 63001 4565 10001
and in the application list, I added a new entry, where 3
is the 0th-indexed 4th entry above.
APPLICATION 4,ROLL,C 1 HOST 3 S
Configuring this as a service
Next we'll configure a systemd
service to make sure this script is always running and ready to accept connections.
I created this file as a “user” service, as ~/.config/systemd/user/rick.service
, but it should probably run as a system service:
# service for RRoAX25 server # replace USER with the username under which you created the bpq-apps venv [Unit] Description="RRoAX25 service" After=network.target [Service] Type=simple WorkingDirectory=/home/USER/.local/bpq-apps/ ExecStart=/home/USER/.local/bpq-apps/bin/python /home/USER/.local/bpq-apps/scripts/rick.py -p 10001 -f /home/USER/.local/bpq-apps/data/messages.json Restart=always [Install] WantedBy=default.target
Activate it by running:
systemctl --user enable rick.service systemctl --user start rick.service
Then check the status to confirm it is working:
systemctl --user status rick.service
If you need to edit the service file, reload it with:
systemctl --user daemon-reload