Esempio n. 1
0
def check(loglevel, config_file, health_url, timeout):
    """APRSD Plugin test app."""

    config = utils.parse_config(config_file)

    setup_logging(config, loglevel, False)
    LOG.debug("APRSD HealthCheck version: {}".format(aprsd.__version__))

    try:
        url = health_url
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()
    except Exception as ex:
        LOG.error("Failed to fetch healthcheck url '{}' : '{}'".format(
            url, ex))
        sys.exit(-1)
    else:
        stats = json.loads(response.text)
        LOG.debug(stats)

        email_thread_last_update = stats["stats"]["email"][
            "thread_last_update"]

        delta = parse_delta_str(email_thread_last_update)
        d = datetime.timedelta(**delta)
        max_timeout = {"hours": 0.0, "minutes": 5, "seconds": 0}
        max_delta = datetime.timedelta(**max_timeout)
        if d > max_delta:
            LOG.error("Email thread is very old! {}".format(d))
            sys.exit(-1)

        sys.exit(0)
Esempio n. 2
0
def server(loglevel, quiet, disable_validation, config_file):
    """Start the aprsd server process."""

    signal.signal(signal.SIGINT, signal_handler)

    click.echo("Load config")
    config = utils.parse_config(config_file)

    # Force setting the config to the modules that need it
    # TODO(Walt): convert these modules to classes that can
    # Accept the config as a constructor param, instead of this
    # hacky global setting
    email.CONFIG = config
    messaging.CONFIG = config

    setup_logging(config, loglevel, quiet)
    LOG.info("APRSD Started version: {}".format(aprsd.__version__))

    # TODO(walt): Make email processing/checking optional?
    # Maybe someone only wants this to process messages with plugins only.
    valid = email.validate_email_config(config, disable_validation)
    if not valid:
        LOG.error("Failed to validate email config options")
        sys.exit(-1)

    # start the email thread
    email.start_thread()

    # Create the initial PM singleton and Register plugins
    plugin_manager = plugin.PluginManager(config)
    plugin_manager.setup_plugins()
    cl = client.Client(config)

    # setup and run the main blocking loop
    while True:
        # Now use the helper which uses the singleton
        aprs_client = client.get_client()

        # setup the consumer of messages and block until a messages
        try:
            # This will register a packet consumer with aprslib
            # When new packets come in the consumer will process
            # the packet
            aprs_client.consumer(process_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
            cl.reset()
Esempio n. 3
0
def main():
    global CONFIG
    args = parser.parse_args()
    setup_logging(args)
    LOG.info("Test APRS server starting.")
    time.sleep(1)

    CONFIG = utils.parse_config(args)

    ip = CONFIG["aprs"]["host"]
    port = CONFIG["aprs"]["port"]
    LOG.info("Start server listening on {}:{}".format(args.ip, args.port))

    with socketserver.TCPServer((ip, port), MyAPRSTCPHandler) as server:
        server.serve_forever()
Esempio n. 4
0
def test_plugin(
    loglevel,
    config_file,
    plugin_path,
    fromcall,
    message,
):
    """APRSD Plugin test app."""

    config = utils.parse_config(config_file)
    email.CONFIG = config

    setup_logging(config, loglevel, False)
    LOG.info("Test APRSD PLugin version: {}".format(aprsd.__version__))
    if type(message) is tuple:
        message = " ".join(message)
    LOG.info("P'{}'  F'{}'   C'{}'".format(plugin_path, fromcall, message))
    client.Client(config)

    pm = plugin.PluginManager(config)
    obj = pm._create_class(plugin_path, plugin.APRSDPluginBase, config=config)

    reply = obj.run(fromcall, message, 1)
    LOG.info("Result = '{}'".format(reply))
Esempio n. 5
0
def send_message(loglevel, quiet, config_file, aprs_login, aprs_password,
                 tocallsign, command):
    """Send a message to a callsign via APRS_IS."""
    global got_ack, got_response

    click.echo("{} {} {} {}".format(aprs_login, aprs_password, tocallsign,
                                    command))

    click.echo("Load config")
    config = utils.parse_config(config_file)
    if not aprs_login:
        click.echo("Must set --aprs_login or APRS_LOGIN")
        return

    if not aprs_password:
        click.echo("Must set --aprs-password or APRS_PASSWORD")
        return

    config["aprs"]["login"] = aprs_login
    config["aprs"]["password"] = aprs_password
    messaging.CONFIG = config

    setup_logging(config, loglevel, quiet)
    LOG.info("APRSD Started version: {}".format(aprsd.__version__))
    message_number = random.randint(1, 90)
    if type(command) is tuple:
        command = " ".join(command)
    LOG.info("Sending Command '{}'".format(command))

    got_ack = False
    got_response = False

    def rx_packet(packet):
        global got_ack, got_response
        # LOG.debug("Got packet back {}".format(packet))
        resp = packet.get("response", None)
        if resp == "ack":
            ack_num = packet.get("msgNo")
            LOG.info("We got ack for our sent message {}".format(ack_num))
            messaging.log_packet(packet)
            got_ack = True
        else:
            message = packet.get("message_text", None)
            LOG.info("We got a new message")
            fromcall = packet["from"]
            msg_number = packet.get("msgNo", None)
            if msg_number:
                ack = msg_number
            else:
                ack = "0"
            messaging.log_message("Received Message",
                                  packet["raw"],
                                  message,
                                  fromcall=fromcall,
                                  ack=ack)
            got_response = True
            # Send the ack back?
            messaging.send_ack_direct(fromcall, ack)

        if got_ack and got_response:
            sys.exit(0)

    cl = client.Client(config)

    # 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
    messaging.send_message_direct(tocallsign, command, message_number)

    try:
        # This will register a packet consumer with aprslib
        # When new packets come in the consumer will process
        # the packet
        aprs_client = client.get_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
        cl.reset()
Esempio n. 6
0
File: main.py Progetto: wa9ecj/aprsd
def server(
    loglevel,
    quiet,
    disable_validation,
    config_file,
    flush,
):
    """Start the aprsd server process."""
    global flask_enabled
    signal.signal(signal.SIGINT, signal_handler)

    if not quiet:
        click.echo("Load config")
    config = utils.parse_config(config_file)

    # Force setting the config to the modules that need it
    # TODO(Walt): convert these modules to classes that can
    # Accept the config as a constructor param, instead of this
    # hacky global setting
    email.CONFIG = config

    setup_logging(config, loglevel, quiet)
    if config["aprsd"].get("trace", False):
        trace.setup_tracing(["method", "api"])
    LOG.info("APRSD Started version: {}".format(aprsd.__version__))
    stats.APRSDStats(config)

    email_enabled = config["aprsd"]["email"].get("enabled", False)

    if email_enabled:
        # TODO(walt): Make email processing/checking optional?
        # Maybe someone only wants this to process messages with plugins only.
        valid = email.validate_email_config(config, disable_validation)
        if not valid:
            LOG.error("Failed to validate email config options")
            sys.exit(-1)
    else:
        LOG.info("Email services not enabled.")

    # Create the initial PM singleton and Register plugins
    plugin_manager = plugin.PluginManager(config)
    plugin_manager.setup_plugins()
    try:
        cl = client.Client(config)
        cl.client
    except LoginError:
        sys.exit(-1)

    # Now load the msgTrack from disk if any
    if flush:
        LOG.debug("Deleting saved MsgTrack.")
        messaging.MsgTrack().flush()
    else:
        # Try and load saved MsgTrack list
        LOG.debug("Loading saved MsgTrack object.")
        messaging.MsgTrack().load()

    rx_msg_queue = queue.Queue(maxsize=20)
    tx_msg_queue = queue.Queue(maxsize=20)
    msg_queues = {"rx": rx_msg_queue, "tx": tx_msg_queue}

    rx_thread = threads.APRSDRXThread(msg_queues=msg_queues, config=config)
    tx_thread = threads.APRSDTXThread(msg_queues=msg_queues, config=config)

    if email_enabled:
        email_thread = email.APRSDEmailThread(msg_queues=msg_queues,
                                              config=config)
        email_thread.start()

    rx_thread.start()
    tx_thread.start()

    messaging.MsgTrack().restart()

    keepalive = threads.KeepAliveThread()
    keepalive.start()

    try:
        web_enabled = utils.check_config_option(config,
                                                ["aprsd", "web", "enabled"])
    except Exception:
        web_enabled = False

    if web_enabled:
        flask_enabled = True
        app = flask.init_flask(config)
        app.run(
            host=config["aprsd"]["web"]["host"],
            port=config["aprsd"]["web"]["port"],
        )

    # If there are items in the msgTracker, then save them
    LOG.info("APRSD Exiting.")
    return 0