Esempio n. 1
0
def send_message_thread(tocall, message, this_message_number, retry_count):
    cl = client.get_client()
    line = "{}>APRS::{}:{}{{{}\n".format(
        CONFIG["aprs"]["login"],
        tocall,
        message,
        str(this_message_number),
    )
    for i in range(retry_count, 0, -1):
        LOG.debug("DEBUG: send_message_thread msg:ack combos are: ")
        LOG.debug(pprint.pformat(ack_dict))
        if ack_dict[this_message_number] != 1:
            log_message(
                "Sending Message",
                line.rstrip("\n"),
                message,
                tocall=tocall,
                retry_number=i,
            )
            # tn.write(line)
            cl.sendall(line)
            # decaying repeats, 31 to 93 second intervals
            sleeptime = (retry_count - i + 1) * 31
            time.sleep(sleeptime)
        else:
            break
    return
Esempio n. 2
0
    def loop(self):
        """Loop until a message is acked or it gets delayed.

        We only sleep for 5 seconds between each loop run, so
        that CTRL-C can exit the app in a short period.  Each sleep
        means the app quitting is blocked until sleep is done.
        So we keep track of the last send attempt and only send if the
        last send attempt is old enough.

        """
        cl = client.get_client()
        tracker = MsgTrack()
        # lets see if the message is still in the tracking queue
        msg = tracker.get(self.msg.id)
        if not msg:
            # The message has been removed from the tracking queue
            # So it got acked and we are done.
            LOG.info("Message Send Complete via Ack.")
            return False
        else:
            send_now = False
            if msg.last_send_attempt == msg.retry_count:
                # we reached the send limit, don't send again
                # TODO(hemna) - Need to put this in a delayed queue?
                LOG.info("Message Send Complete. Max attempts reached.")
                return False

            # Message is still outstanding and needs to be acked.
            if msg.last_send_time:
                # Message has a last send time tracking
                now = datetime.datetime.now()
                sleeptime = (msg.last_send_attempt + 1) * 31
                delta = now - msg.last_send_time
                if delta > datetime.timedelta(seconds=sleeptime):
                    # It's time to try to send it again
                    send_now = True
            else:
                send_now = True

            if send_now:
                # no attempt time, so lets send it, and start
                # tracking the time.
                log_message(
                    "Sending Message",
                    str(msg).rstrip("\n"),
                    msg.message,
                    tocall=self.msg.tocall,
                    retry_number=msg.last_send_attempt,
                    msg_num=msg.id,
                )
                cl.sendall(str(msg))
                stats.APRSDStats().msgs_tx_inc()
                msg.last_send_time = datetime.datetime.now()
                msg.last_send_attempt += 1

            time.sleep(5)
            # Make sure we get called again.
            return True
Esempio n. 3
0
 def send_direct(self):
     """Send an ack message without a separate thread."""
     cl = client.get_client()
     log_message(
         "Sending ack",
         str(self).rstrip("\n"),
         None,
         ack=self.id,
         tocall=self.tocall,
         fromcall=self.fromcall,
     )
     cl.sendall(str(self))
Esempio n. 4
0
 def send_direct(self):
     """Send a message without a separate thread."""
     cl = client.get_client()
     log_message(
         "Sending Message Direct",
         str(self).rstrip("\n"),
         self.message,
         tocall=self.tocall,
         fromcall=self.fromcall,
     )
     cl.sendall(str(self))
     stats.APRSDStats().msgs_tx_inc()
Esempio n. 5
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. 6
0
def send_ack_direct(tocall, ack):
    """Send an ack message without a separate thread."""
    LOG.debug("Send ACK({}:{}) to radio.".format(tocall, ack))
    cl = client.get_client()
    fromcall = CONFIG["aprs"]["login"]
    line = "{}>APRS::{}:ack{}\n".format(fromcall, tocall, ack)
    log_message(
        "Sending ack",
        line.rstrip("\n"),
        None,
        ack=ack,
        tocall=tocall,
        fromcall=fromcall,
    )
    cl.sendall(line)
Esempio n. 7
0
 def send_thread(self):
     """Separate thread to send acks with retries."""
     cl = client.get_client()
     for i in range(self.retry_count, 0, -1):
         log_message(
             "Sending ack",
             str(self).rstrip("\n"),
             None,
             ack=self.id,
             tocall=self.tocall,
             retry_number=i,
         )
         cl.sendall(str(self))
         stats.APRSDStats().ack_tx_inc()
         # aprs duplicate detection is 30 secs?
         # (21 only sends first, 28 skips middle)
         time.sleep(31)
Esempio n. 8
0
def send_ack_thread(tocall, ack, retry_count):
    cl = client.get_client()
    tocall = tocall.ljust(9)  # pad to nine chars
    line = "{}>APRS::{}:ack{}\n".format(CONFIG["aprs"]["login"], tocall, ack)
    for i in range(retry_count, 0, -1):
        log_message(
            "Sending ack",
            line.rstrip("\n"),
            None,
            ack=ack,
            tocall=tocall,
            retry_number=i,
        )
        cl.sendall(line)
        # aprs duplicate detection is 30 secs?
        # (21 only sends first, 28 skips middle)
        time.sleep(31)
Esempio n. 9
0
def send_message_direct(tocall, message, message_number=None):
    """Send a message without a separate thread."""
    cl = client.get_client()
    if not message_number:
        this_message_number = 1
    else:
        this_message_number = message_number
    fromcall = CONFIG["aprs"]["login"]
    line = "{}>APRS::{}:{}{{{}\n".format(
        fromcall,
        tocall,
        message,
        str(this_message_number),
    )
    LOG.debug("DEBUG: send_message_thread msg:ack combos are: ")
    log_message(
        "Sending Message", line.rstrip("\n"), message, tocall=tocall, fromcall=fromcall
    )
    cl.sendall(line)
Esempio n. 10
0
    def loop(self):
        """Separate thread to send acks with retries."""
        send_now = False
        if self.ack.last_send_attempt == self.ack.retry_count:
            # we reached the send limit, don't send again
            # TODO(hemna) - Need to put this in a delayed queue?
            LOG.info("Ack Send Complete. Max attempts reached.")
            return False

        if self.ack.last_send_time:
            # Message has a last send time tracking
            now = datetime.datetime.now()

            # aprs duplicate detection is 30 secs?
            # (21 only sends first, 28 skips middle)
            sleeptime = 31
            delta = now - self.ack.last_send_time
            if delta > datetime.timedelta(seconds=sleeptime):
                # It's time to try to send it again
                send_now = True
            else:
                LOG.debug("Still wating. {}".format(delta))
        else:
            send_now = True

        if send_now:
            cl = client.get_client()
            log_message(
                "Sending ack",
                str(self.ack).rstrip("\n"),
                None,
                ack=self.ack.id,
                tocall=self.ack.tocall,
                retry_number=self.ack.last_send_attempt,
            )
            cl.sendall(str(self.ack))
            stats.APRSDStats().ack_tx_inc()
            self.ack.last_send_attempt += 1
            self.ack.last_send_time = datetime.datetime.now()
        time.sleep(5)
Esempio n. 11
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()