mirror of https://github.com/craigerl/aprsd.git
Added nearest repeaters plugin
This patch adds the new POC nearest repeaters plugin. It will fetch the closest N repeaters to a callsign's last known GPS coordinates. By default will return 2m repeaters, but has the option to return other bands. "n 3" - return the closest 3 repeaters in 2m band "n 1" - return the 1 closest 2m band repeater "n 70cm" - return the 1 closest 70cm band repeater "n 3 70cm" - return the 3 closest 70cm band repeaters This patch also updates the message thread to accept a list of messages to send as a return from a plugin. This results in N aprs messages being sent as a reply to a command. This was needed by the nearest plugin to allow it to return a repeater per message as a response.
This commit is contained in:
parent
ed4995b6eb
commit
6d2880104d
|
@ -0,0 +1,104 @@
|
|||
import logging
|
||||
|
||||
from aprsd import plugin, plugin_utils, trace, utils
|
||||
import requests
|
||||
|
||||
LOG = logging.getLogger("APRSD")
|
||||
|
||||
|
||||
class NearestPlugin(plugin.APRSDMessagePluginBase):
|
||||
"""Nearest!
|
||||
|
||||
Syntax of request
|
||||
|
||||
n[earest] [count] [band]
|
||||
|
||||
count - the number of stations to return
|
||||
band - the frequency band to look for
|
||||
Defaults to 2m
|
||||
|
||||
|
||||
"""
|
||||
|
||||
version = "1.0"
|
||||
command_regex = "^[nN]"
|
||||
command_name = "nearest"
|
||||
|
||||
@trace.trace
|
||||
def command(self, packet):
|
||||
LOG.info("Nearest Plugin")
|
||||
fromcall = packet.get("from")
|
||||
message = packet.get("message_text", None)
|
||||
# ack = packet.get("msgNo", "0")
|
||||
|
||||
# get last location of a callsign, get descriptive name from weather service
|
||||
try:
|
||||
utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"])
|
||||
except Exception as ex:
|
||||
LOG.error("Failed to find config aprs.fi:apikey {}".format(ex))
|
||||
return "No aprs.fi apikey found"
|
||||
|
||||
api_key = self.config["services"]["aprs.fi"]["apiKey"]
|
||||
|
||||
try:
|
||||
aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall)
|
||||
except Exception as ex:
|
||||
LOG.error("Failed to fetch aprs.fi '{}'".format(ex))
|
||||
return "Failed to fetch aprs.fi location"
|
||||
|
||||
LOG.debug("NearestPlugin: aprs_data = {}".format(aprs_data))
|
||||
if not len(aprs_data["entries"]):
|
||||
LOG.error("Didn't get any entries from aprs.fi")
|
||||
return "Failed to fetch aprs.fi location"
|
||||
|
||||
lat = aprs_data["entries"][0]["lat"]
|
||||
lon = aprs_data["entries"][0]["lng"]
|
||||
|
||||
command_parts = message.split(" ")
|
||||
# try and decipher the request parameters
|
||||
# n[earest] should be part[0]
|
||||
# part[1] could be
|
||||
if len(command_parts) == 3:
|
||||
# Must be in
|
||||
count = command_parts[1]
|
||||
band = command_parts[2]
|
||||
elif len(command_parts) == 2:
|
||||
if "m" in command_parts[1]:
|
||||
band = command_parts[1]
|
||||
count = 1
|
||||
else:
|
||||
count = command_parts[1]
|
||||
band = "2m"
|
||||
else:
|
||||
count = 1
|
||||
band = "2m"
|
||||
|
||||
LOG.info("Looking for {} nearest stations in band {}".format(count, band))
|
||||
|
||||
try:
|
||||
url = "http://0.0.0.0:8081/nearest"
|
||||
parameters = {"lat": lat, "lon": lon, "count": count, "band": band}
|
||||
result = requests.post(url=url, params=parameters)
|
||||
data = result.json()
|
||||
LOG.info(data)
|
||||
except Exception as ex:
|
||||
LOG.error("Couldn't fetch nearest stations '{}'".format(ex))
|
||||
data = None
|
||||
|
||||
if data:
|
||||
# just do the first one for now
|
||||
replies = []
|
||||
for entry in data:
|
||||
LOG.info("Using {}".format(entry))
|
||||
reply = "{} {} PL{} {}m {}".format(
|
||||
entry["callsign"],
|
||||
entry["frequency"],
|
||||
entry["offset"],
|
||||
entry["distance"],
|
||||
entry["direction"],
|
||||
)
|
||||
replies.append(reply)
|
||||
|
||||
return replies
|
||||
else:
|
||||
return "Failed"
|
|
@ -253,21 +253,35 @@ class APRSDRXThread(APRSDThread):
|
|||
try:
|
||||
results = pm.run(packet)
|
||||
for reply in results:
|
||||
found_command = True
|
||||
# A plugin can return a null message flag which signals
|
||||
# us that they processed the message correctly, but have
|
||||
# nothing to reply with, so we avoid replying with a usage string
|
||||
if reply is not messaging.NULL_MESSAGE:
|
||||
LOG.debug("Sending '{}'".format(reply))
|
||||
if isinstance(reply, list):
|
||||
# one of the plugins wants to send multiple messages
|
||||
found_command = True
|
||||
for subreply in reply:
|
||||
LOG.debug("Sending '{}'".format(subreply))
|
||||
|
||||
msg = messaging.TextMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
subreply,
|
||||
)
|
||||
self.msg_queues["tx"].put(msg)
|
||||
|
||||
msg = messaging.TextMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
)
|
||||
self.msg_queues["tx"].put(msg)
|
||||
else:
|
||||
LOG.debug("Got NULL MESSAGE from plugin")
|
||||
found_command = True
|
||||
# A plugin can return a null message flag which signals
|
||||
# us that they processed the message correctly, but have
|
||||
# nothing to reply with, so we avoid replying with a usage string
|
||||
if reply is not messaging.NULL_MESSAGE:
|
||||
LOG.debug("Sending '{}'".format(reply))
|
||||
|
||||
msg = messaging.TextMessage(
|
||||
self.config["aprs"]["login"],
|
||||
fromcall,
|
||||
reply,
|
||||
)
|
||||
self.msg_queues["tx"].put(msg)
|
||||
else:
|
||||
LOG.debug("Got NULL MESSAGE from plugin")
|
||||
|
||||
if not found_command:
|
||||
plugins = pm.get_msg_plugins()
|
||||
|
|
Loading…
Reference in New Issue