First pass
This commit is contained in:
parent
fa05a668e0
commit
ec06d78bb6
|
|
@ -0,0 +1,25 @@
|
|||
# mqtt-aprs
|
||||
Connects to the specified APRS-IS server, and posts the APRS output to MQTT. Can parse parameters, or dump the raw JSON.
|
||||
|
||||
This script uses the aprslib python function to do the heavy APRS lifting.
|
||||
|
||||
INSTALL
|
||||
=================
|
||||
```
|
||||
sudo apt-get install git python-pip
|
||||
|
||||
sudo pip install setuptools
|
||||
sudo pip install setproctitle
|
||||
sudo pip install paho-mqtt
|
||||
sudo pip install aprslib
|
||||
|
||||
mkdir /etc/mqtt-aprs/
|
||||
git clone git://github.com/mloebl/mqtt-mqtt-aprs.git /usr/local/mqtt-aprs/
|
||||
cp /usr/local/mqtt-aprs/mqtt-aprs.cfg.example /etc/mqtt-aprs/mqtt-aprs.cfg
|
||||
cp /usr/local/mqtt-aprs/mqtt-aprs.init /etc/init.d/mqtt-aprs
|
||||
pdate-rc.d mqtt-aprs defaults
|
||||
cp /usr/local/mqtt-aprsp/mqtt-aprs.default /etc/default/mqtt-aprs
|
||||
```
|
||||
Edit /etc/default/mqtt-aprs and /etc/mqtt-aprs/mqtt-aprs.cfg to suit:
|
||||
|
||||
`/etc/init.d/mqtt-aprs start`
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
[global]
|
||||
DEBUG = False
|
||||
LOGFILE = /var/log/mqtt-aprs.log
|
||||
MQTT_HOST = 10.0.0.1
|
||||
MQTT_PORT = 1883
|
||||
MQTT_TOPIC = /#
|
||||
MQTT_SUBTOPIC = aprs
|
||||
MQTT_USERNAME =
|
||||
MQTT_PASSWORD =
|
||||
APRS_LATITUDE = 0.00000
|
||||
APRS_LONGITUDE = 0.00000
|
||||
APRS_CALLSIGN = N0CALL
|
||||
APRS_PASSWORD = -1
|
||||
APRS_HOST =
|
||||
APRS_PORT =
|
||||
APRS_FILTER =
|
||||
APRS_PROCESS = True
|
||||
METRICUNITS = 0
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
START_DAEMON=true
|
||||
VERBOSE=true
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: mqtt-aprs
|
||||
# Required-Start: $remote_fs $syslog $network
|
||||
# Should-Start: bluetooth dbus udev
|
||||
# Required-Stop: $remote_fs $syslog $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: mqtt-aprs daemon start/stop script
|
||||
# Description: Start/Stop script for the mqtt-aprs daemon
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Kyle Gordon <kyle@lodge.glasgownet.com
|
||||
# Modified by Mike Loebl for custom usage
|
||||
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="mqtt-aprs daemon"
|
||||
NAME=mqtt-aprs
|
||||
DAEMON=/usr/local/$NAME/$NAME.py
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
echo "Starting mqtt-aprs"
|
||||
start-stop-daemon -b --start --quiet -m --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon -b --start --quiet -m --pidfile $PIDFILE --exec $DAEMON -- \
|
||||
$OPTIONS \
|
||||
|| return 2
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ "$START_DAEMON" = "true" ]; then
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
else
|
||||
[ "$VERBOSE" != no ] && \
|
||||
log_daemon_msg "Not starting $DESC" "$NAME" && \
|
||||
log_end_msg 0
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
reload|force-reload)
|
||||
log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
do_reload
|
||||
log_end_msg $?
|
||||
;;
|
||||
restart)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
||||
|
|
@ -0,0 +1,399 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
|
||||
__author__ = "Mike Loebl"
|
||||
__copyright__ = "Copyright (C) Mike Loebl"
|
||||
|
||||
# Script based on mqtt-owfs-temp written by Kyle Gordon and converted for use with APRS
|
||||
# Source: https://github.com/kylegordon/mqtt-owfs-temp
|
||||
|
||||
import os
|
||||
import logging
|
||||
import signal
|
||||
import socket
|
||||
import time
|
||||
import sys
|
||||
import binascii
|
||||
|
||||
import paho.mqtt.client as paho
|
||||
import ConfigParser
|
||||
|
||||
import setproctitle
|
||||
|
||||
import aprslib
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Read the config file
|
||||
config = ConfigParser.RawConfigParser()
|
||||
# TODO: Fix path:
|
||||
config.read("./mqtt-aprs.cfg")
|
||||
|
||||
# Use ConfigParser to pick out the settings
|
||||
DEBUG = config.getboolean("global", "debug")
|
||||
LOGFILE = config.get("global", "logfile")
|
||||
MQTT_HOST = config.get("global", "mqtt_host")
|
||||
MQTT_PORT = config.getint("global", "mqtt_port")
|
||||
MQTT_SUBTOPIC = config.get("global", "MQTT_SUBTOPIC")
|
||||
MQTT_TOPIC = "/raw/" + socket.getfqdn() + "/" + MQTT_SUBTOPIC
|
||||
MQTT_USERNAME = config.get("global", "MQTT_USERNAME")
|
||||
MQTT_PASSWORD = config.get("global", "MQTT_PASSWORD")
|
||||
METRICUNITS = config.get("global", "METRICUNITS")
|
||||
|
||||
APRS_CALLSIGN = config.get("global", "APRS_CALLSIGN")
|
||||
APRS_PASSWORD = config.get("global", "APRS_PASSWORD")
|
||||
APRS_HOST = config.get("global", "APRS_HOST")
|
||||
APRS_PORT = config.get("global", "APRS_PORT")
|
||||
APRS_FILTER = config.get("global", "APRS_FILTER")
|
||||
APRS_PROCESS = config.get("global", "APRS_PROCESS")
|
||||
|
||||
APRS_LATITUDE = config.get("global", "APRS_LATITUDE")
|
||||
APRS_LONGITUDE = config.get("global", "APRS_LONGITUDE")
|
||||
|
||||
APPNAME = MQTT_SUBTOPIC
|
||||
PRESENCETOPIC = "clients/" + socket.getfqdn() + "/" + APPNAME + "/state"
|
||||
setproctitle.setproctitle(APPNAME)
|
||||
client_id = APPNAME + "_%d" % os.getpid()
|
||||
|
||||
mqttc = paho.Client()
|
||||
|
||||
LOGFORMAT = '%(asctime)-15s %(message)s'
|
||||
|
||||
if DEBUG:
|
||||
logging.basicConfig(filename=LOGFILE,
|
||||
level=logging.DEBUG,
|
||||
format=LOGFORMAT)
|
||||
else:
|
||||
logging.basicConfig(filename=LOGFILE,
|
||||
level=logging.INFO,
|
||||
format=LOGFORMAT)
|
||||
|
||||
logging.info("Starting " + APPNAME)
|
||||
logging.info("INFO MODE")
|
||||
logging.debug("DEBUG MODE")
|
||||
|
||||
def celsiusCon(farenheit):
|
||||
return (farenheit - 32)*(5/9)
|
||||
def farenheitCon(celsius):
|
||||
return ((celsius*(9/5)) + 32)
|
||||
|
||||
# All the MQTT callbacks start here
|
||||
|
||||
|
||||
def on_publish(mosq, obj, mid):
|
||||
"""
|
||||
What to do when a message is published
|
||||
"""
|
||||
logging.debug("MID " + str(mid) + " published.")
|
||||
|
||||
|
||||
def on_subscribe(mosq, obj, mid, qos_list):
|
||||
"""
|
||||
What to do in the event of subscribing to a topic"
|
||||
"""
|
||||
logging.debug("Subscribe with mid " + str(mid) + " received.")
|
||||
|
||||
|
||||
def on_unsubscribe(mosq, obj, mid):
|
||||
"""
|
||||
What to do in the event of unsubscribing from a topic
|
||||
"""
|
||||
logging.debug("Unsubscribe with mid " + str(mid) + " received.")
|
||||
|
||||
|
||||
def on_connect(self, mosq, obj, result_code):
|
||||
"""
|
||||
Handle connections (or failures) to the broker.
|
||||
This is called after the client has received a CONNACK message
|
||||
from the broker in response to calling connect().
|
||||
The parameter rc is an integer giving the return code:
|
||||
0: Success
|
||||
1: Refused – unacceptable protocol version
|
||||
2: Refused – identifier rejected
|
||||
3: Refused – server unavailable
|
||||
4: Refused – bad user name or password (MQTT v3.1 broker only)
|
||||
5: Refused – not authorised (MQTT v3.1 broker only)
|
||||
"""
|
||||
logging.debug("on_connect RC: " + str(result_code))
|
||||
if result_code == 0:
|
||||
logging.info("Connected to %s:%s", MQTT_HOST, MQTT_PORT)
|
||||
# Publish retained LWT as per
|
||||
# http://stackoverflow.com/q/97694
|
||||
# See also the will_set function in connect() below
|
||||
mqttc.publish(PRESENCETOPIC, "1", retain=True)
|
||||
process_connection()
|
||||
elif result_code == 1:
|
||||
logging.info("Connection refused - unacceptable protocol version")
|
||||
cleanup()
|
||||
elif result_code == 2:
|
||||
logging.info("Connection refused - identifier rejected")
|
||||
cleanup()
|
||||
elif result_code == 3:
|
||||
logging.info("Connection refused - server unavailable")
|
||||
logging.info("Retrying in 30 seconds")
|
||||
time.sleep(30)
|
||||
elif result_code == 4:
|
||||
logging.info("Connection refused - bad user name or password")
|
||||
cleanup()
|
||||
elif result_code == 5:
|
||||
logging.info("Connection refused - not authorised")
|
||||
cleanup()
|
||||
else:
|
||||
logging.warning("Something went wrong. RC:" + str(result_code))
|
||||
cleanup()
|
||||
|
||||
|
||||
def on_disconnect(mosq, obj, result_code):
|
||||
"""
|
||||
Handle disconnections from the broker
|
||||
"""
|
||||
if result_code == 0:
|
||||
logging.info("Clean disconnection")
|
||||
else:
|
||||
logging.info("Unexpected disconnection! Reconnecting in 5 seconds")
|
||||
logging.debug("Result code: %s", result_code)
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def on_message(mosq, obj, msg):
|
||||
"""
|
||||
What to do when the client recieves a message from the broker
|
||||
"""
|
||||
logging.debug("Received: " + msg.payload +
|
||||
" received on topic " + msg.topic +
|
||||
" with QoS " + str(msg.qos))
|
||||
process_message(msg)
|
||||
|
||||
|
||||
def on_log(mosq, obj, level, string):
|
||||
"""
|
||||
What to do with debug log output from the MQTT library
|
||||
"""
|
||||
logging.debug(string)
|
||||
|
||||
# End of MQTT callbacks
|
||||
|
||||
|
||||
def cleanup(signum, frame):
|
||||
"""
|
||||
Signal handler to ensure we disconnect cleanly
|
||||
in the event of a SIGTERM or SIGINT.
|
||||
"""
|
||||
logging.info("Disconnecting from broker")
|
||||
# Publish a retained message to state that this client is offline
|
||||
mqttc.publish(PRESENCETOPIC, "0", retain=True)
|
||||
mqttc.disconnect()
|
||||
mqttc.loop_stop()
|
||||
logging.info("Exiting on signal %d", signum)
|
||||
sys.exit(signum)
|
||||
|
||||
def connect():
|
||||
"""
|
||||
Connect to the broker, define the callbacks, and subscribe
|
||||
This will also set the Last Will and Testament (LWT)
|
||||
The LWT will be published in the event of an unclean or
|
||||
unexpected disconnection.
|
||||
"""
|
||||
logging.info("Connecting to %s:%s", MQTT_HOST, MQTT_PORT)
|
||||
|
||||
if MQTT_USERNAME:
|
||||
logging.info("Found username %s", MQTT_USERNAME)
|
||||
mqttc.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
|
||||
|
||||
# Set the Last Will and Testament (LWT) *before* connecting
|
||||
mqttc.will_set(PRESENCETOPIC, "0", qos=0, retain=True)
|
||||
result = mqttc.connect(MQTT_HOST, MQTT_PORT, 60)
|
||||
if result != 0:
|
||||
logging.info("Connection failed with error code %s. Retrying", result)
|
||||
|
||||
time.sleep(10)
|
||||
connect()
|
||||
|
||||
# Define the callbacks
|
||||
mqttc.on_connect = on_connect
|
||||
mqttc.on_disconnect = on_disconnect
|
||||
mqttc.on_publish = on_publish
|
||||
mqttc.on_subscribe = on_subscribe
|
||||
mqttc.on_unsubscribe = on_unsubscribe
|
||||
mqttc.on_message = on_message
|
||||
if DEBUG:
|
||||
mqttc.on_log = on_log
|
||||
|
||||
mqttc.loop_start()
|
||||
|
||||
def process_connection():
|
||||
"""
|
||||
What to do when a new connection is established
|
||||
"""
|
||||
logging.debug("Processing connection")
|
||||
|
||||
|
||||
def process_message(mosq, obj, msg):
|
||||
"""
|
||||
What to do with the message that's arrived
|
||||
"""
|
||||
logging.debug("Received: %s", msg.topic)
|
||||
|
||||
|
||||
def find_in_sublists(lst, value):
|
||||
for sub_i, sublist in enumerate(lst):
|
||||
try:
|
||||
return (sub_i, sublist.index(value))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
raise ValueError("%s is not in lists" % value)
|
||||
|
||||
def callback(packet):
|
||||
logging.debug("Raw Packet: %s", packet)
|
||||
|
||||
if APRS_PROCESS == "True":
|
||||
aprspacket = aprs._parse(packet)
|
||||
|
||||
ssid = aprspacket.get('from', None)
|
||||
logging.debug("SSID: %s", ssid)
|
||||
|
||||
|
||||
rawpacket = aprspacket.get('raw', None)
|
||||
logging.debug("RAW: %s", rawpacket)
|
||||
publish_aprstomqtt(ssid, "raw", rawpacket)
|
||||
|
||||
aprspath = aprspacket.get('path', None)
|
||||
if aprspath:
|
||||
logging.debug("path: %s", aprspath)
|
||||
publish_aprstomqtt(ssid, "path",aprspath)
|
||||
|
||||
|
||||
packet_format = aprspacket.get('format', None)
|
||||
logging.debug("format: %s", packet_format)
|
||||
publish_aprstomqtt(ssid, "format", packet_format)
|
||||
|
||||
symbol_table = aprspacket.get('symbol_table', None)
|
||||
symbol = aprspacket.get('symbol', None)
|
||||
|
||||
if symbol_table and symbol:
|
||||
icon = symbol_table + symbol
|
||||
logging.debug("icon: %s", icon)
|
||||
publish_aprstomqtt(ssid, "icon", icon)
|
||||
|
||||
aprs_lat = aprspacket.get('latitude', None)
|
||||
aprs_lon = aprspacket.get('longitude', None)
|
||||
if aprs_lat and aprs_lon:
|
||||
aprs_lat = round(aprs_lat, 4)
|
||||
aprs_lon = round(aprs_lon, 4)
|
||||
logging.debug("latitude: %s", aprs_lat)
|
||||
logging.debug("longitude: %s", aprs_lon)
|
||||
distance = get_distance(aprs_lat, aprs_lon)
|
||||
publish_aprstomqtt(ssid, "latitude", aprs_lat)
|
||||
publish_aprstomqtt(ssid, "longitude",aprs_lon)
|
||||
|
||||
logging.debug("Distance away: %s", distance)
|
||||
publish_aprstomqtt(ssid, "distance",distance)
|
||||
|
||||
altitude = aprspacket.get('altitude', None)
|
||||
if altitude:
|
||||
if METRICUNITS is "0":
|
||||
altitude = altitude / 0.3048
|
||||
logging.debug("altitude: %s", altitude)
|
||||
publish_aprstomqtt(ssid, "altitude",altitude)
|
||||
|
||||
comment = aprspacket.get('comment', None)
|
||||
if comment:
|
||||
logging.debug("comment: %s", comment)
|
||||
publish_aprstomqtt(ssid, "comment",comment)
|
||||
|
||||
telemetry = aprspacket.get('telemetry', None)
|
||||
if telemetry:
|
||||
logging.debug("telemetry: %s", telemetry)
|
||||
publish_aprstomqtt(ssid, "telemetry",telemetry)
|
||||
|
||||
message = aprspacket.get('message_text', None)
|
||||
if message:
|
||||
logging.debug("message: %s", message)
|
||||
publish_aprstomqtt(ssid, "message",message)
|
||||
else:
|
||||
publish_aprstomqtt_nossid(packet)
|
||||
|
||||
|
||||
def publish_aprstomqtt(inssid, inname, invalue):
|
||||
topic_path = MQTT_TOPIC + "/" + inssid + "/" + inname
|
||||
logging.debug("Publishing topic: %s with value %s" % (topic_path, invalue))
|
||||
mqttc.publish(topic_path, unicode(invalue).encode('utf-8').strip())
|
||||
|
||||
def publish_aprstomqtt_nossid(invalue):
|
||||
topic_path = MQTT_TOPIC
|
||||
logging.debug("Publishing topic: %s with value %s" % (topic_path, invalue))
|
||||
mqttc.publish(topic_path, unicode(invalue).encode('utf-8').strip())
|
||||
|
||||
|
||||
def get_distance(inlat, inlon):
|
||||
if APRS_LATITUDE and APRS_LONGITUDE:
|
||||
# From: https://stackoverflow.com/questions/19412462/getting-distance-between-two-points-based-on-latitude-longitude
|
||||
# approximate radius of earth in km
|
||||
R = 6373.0
|
||||
|
||||
from math import sin, cos, sqrt, atan2, radians
|
||||
lat1 = radians(float(APRS_LATITUDE))
|
||||
lon1 = radians(float(APRS_LONGITUDE))
|
||||
lat2 = radians(float(inlat))
|
||||
lon2 = radians(float(inlon))
|
||||
|
||||
dlon = lon2 - lon1
|
||||
dlat = lat2 - lat1
|
||||
|
||||
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
|
||||
c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
||||
|
||||
distance = R * c
|
||||
|
||||
if METRICUNITS is "0":
|
||||
distance = distance * 0.621371
|
||||
|
||||
return round(distance, 2)
|
||||
|
||||
def aprs_connect():
|
||||
|
||||
|
||||
# Listen for specific packet
|
||||
aprs.set_filter(APRS_FILTER)
|
||||
|
||||
# Open the APRS connection to the server
|
||||
aprs.connect(blocking=True)
|
||||
|
||||
logging.debug("APRS Processing: %s", APRS_PROCESS)
|
||||
# Set a callback for when a packet is received
|
||||
if APRS_PROCESS == "True":
|
||||
aprs.consumer(callback, raw=True)
|
||||
else:
|
||||
aprs.consumer(callback)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Use the signal module to handle signals
|
||||
signal.signal(signal.SIGTERM, cleanup)
|
||||
signal.signal(signal.SIGINT, cleanup)
|
||||
try:
|
||||
# Prepare the APRS connection
|
||||
aprs = aprslib.IS(APRS_CALLSIGN,
|
||||
passwd=APRS_PASSWORD,
|
||||
host=APRS_HOST,
|
||||
port=APRS_PORT,
|
||||
skip_login=False)
|
||||
|
||||
# Connect to the broker and enter the main loop
|
||||
connect()
|
||||
aprs_connect()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logging.info("Interrupted by keypress")
|
||||
sys.exit(0)
|
||||
except aprslib.exceptions.ConnectionDrop:
|
||||
logging.info("Connection to APRS server dropped, trying again in 30 seconds...")
|
||||
time.sleep(30)
|
||||
aprs_connect
|
||||
except aprslib.exceptions.ConnectionError:
|
||||
logging.info("Connection to APRS server failed, trying again in 30 seconds...")
|
||||
time.sleep(30)
|
||||
aprs_connect
|
||||
Loading…
Reference in New Issue