1
0
mirror of https://github.com/craigerl/aprsd.git synced 2026-03-10 01:49:36 -04:00
aprsd/aprsd/cmds/send_message.py
Hemna a656d93263 Added new PacketCollector
this patch adds the new PacketCollector class.
It's a single point for collecting information about
packets sent and recieved from the APRS client.
Basically instead of having the packetlist call the seen list
when we get a packet, we simply call the PacketCollector.rx(),
which in turn calls each registered PacketMonitor class.

This allows us to decouple the packet stats like classses inside
of APRSD.  More importantly, it allows extensions to append their
own PacketMonitor class to the chain without modifying ARPSD.
2024-04-16 14:34:14 -04:00

175 lines
4.6 KiB
Python

import logging
import sys
import time
import aprslib
from aprslib.exceptions import LoginError
import click
from oslo_config import cfg
import aprsd
from aprsd import cli_helper, client, packets
from aprsd import conf # noqa : F401
from aprsd.main import cli
from aprsd.packets import collector
from aprsd.threads import tx
CONF = cfg.CONF
LOG = logging.getLogger("APRSD")
@cli.command()
@cli_helper.add_options(cli_helper.common_options)
@click.option(
"--aprs-login",
envvar="APRS_LOGIN",
show_envvar=True,
help="What callsign to send the message from. Defaults to config entry.",
)
@click.option(
"--aprs-password",
envvar="APRS_PASSWORD",
show_envvar=True,
help="the APRS-IS password for APRS_LOGIN. Defaults to config entry.",
)
@click.option(
"--no-ack",
"-n",
is_flag=True,
show_default=True,
default=False,
help="Don't wait for an ack, just sent it to APRS-IS and bail.",
)
@click.option(
"--wait-response",
"-w",
is_flag=True,
show_default=True,
default=False,
help="Wait for a response to the message?",
)
@click.option("--raw", default=None, help="Send a raw message. Implies --no-ack")
@click.argument("tocallsign", required=True)
@click.argument("command", nargs=-1, required=True)
@click.pass_context
@cli_helper.process_standard_options
def send_message(
ctx,
aprs_login,
aprs_password,
no_ack,
wait_response,
raw,
tocallsign,
command,
):
"""Send a message to a callsign via APRS_IS."""
global got_ack, got_response
quiet = ctx.obj["quiet"]
if not aprs_login:
if CONF.aprs_network.login == conf.client.DEFAULT_LOGIN:
click.echo("Must set --aprs_login or APRS_LOGIN")
ctx.exit(-1)
return
else:
aprs_login = CONF.aprs_network.login
if not aprs_password:
if not CONF.aprs_network.password:
click.echo("Must set --aprs-password or APRS_PASSWORD")
ctx.exit(-1)
return
else:
aprs_password = CONF.aprs_network.password
LOG.info(f"APRSD LISTEN Started version: {aprsd.__version__}")
if type(command) is tuple:
command = " ".join(command)
if not quiet:
if raw:
LOG.info(f"L'{aprs_login}' R'{raw}'")
else:
LOG.info(f"L'{aprs_login}' To'{tocallsign}' C'{command}'")
packets.PacketList()
packets.WatchList()
packets.SeenList()
got_ack = False
got_response = False
def rx_packet(packet):
global got_ack, got_response
cl = client.factory.create()
packet = cl.decode_packet(packet)
collector.PacketCollector().rx(packet)
packet.log("RX")
# LOG.debug("Got packet back {}".format(packet))
if isinstance(packet, packets.AckPacket):
got_ack = True
else:
got_response = True
from_call = packet.from_call
our_call = CONF.callsign.lower()
tx.send(
packets.AckPacket(
from_call=our_call,
to_call=from_call,
msgNo=packet.msgNo,
),
direct=True,
)
if got_ack:
if wait_response:
if got_response:
sys.exit(0)
else:
sys.exit(0)
try:
client.ClientFactory.setup()
client.factory.create().client
except LoginError:
sys.exit(-1)
# Send a message
# then we setup a consumer to rx messages
# We should get an ack back as well as a new message
# we should bail after we get the ack and send an ack back for the
# message
if raw:
tx.send(
packets.Packet(from_call="", to_call="", raw=raw),
direct=True,
)
sys.exit(0)
else:
tx.send(
packets.MessagePacket(
from_call=aprs_login,
to_call=tocallsign,
message_text=command,
),
direct=True,
)
if no_ack:
sys.exit(0)
try:
# This will register a packet consumer with aprslib
# When new packets come in the consumer will process
# the packet
aprs_client = client.factory.create().client
aprs_client.consumer(rx_packet, raw=False)
except aprslib.exceptions.ConnectionDrop:
LOG.error("Connection dropped, reconnecting")
time.sleep(5)
# Force the deletion of the client object connected to aprs
# This will cause a reconnect, next time client.get_client()
# is called
aprs_client.reset()