2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								#!/usr/bin/python3
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								############################################################################
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## ir-aprsisd
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	This is a KML-feed to APRS-IS forwarding daemon.  It was written
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	for Garmin/DeLorme inReach devices, but might work elsewhere too.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	It polls a KML feed in which it expects to find a point in rougly
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	the form that the inReach online feeds use, with attendant course
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	and altitude data.  It transfers each new point found there to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	APRS-IS.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##	K0SIN
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								##
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								###########################################################################
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import aprslib
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import urllib.request
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import xml.dom.minidom
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import time, calendar, math, re
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import platform, sys, os, signal
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import configparser
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from optparse import OptionParser
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Name of our configuration file.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								cf = "ir-aprsisd.cfg"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Command-line options
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								op = OptionParser()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								op.add_option("-C","--config",action="store",type="string",dest="config",help="Load the named configuration file.")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								op.add_option("-s","--ssid",action="store",type="string",dest="ssid",help="APRS SSID")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								op.add_option("-p","--pass",action="store",type="int",dest="passwd",help="APRS-IS password")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								op.add_option("--port",action="store",type="int",dest="port",help="APRS-IS port")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								op.add_option("-u","--user",action="store",type="string",dest="user",help="inReach username")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								op.add_option("-P","--irpass",action="store",type="string",dest="irpass",help="inReach feed password")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								op.add_option("-U","--url",action="store",type="string",dest="url",help="URL for KML feed")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								op.add_option("-i","--imei",action="store",type="int",dest="imei",help="This instance should watch *only* for the single IMEI given in this option.  For a more complicated mapping, use the Device section in the configuration file.")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								op.add_option("-c","--comment",action="store",type="string",dest="comment",help="APRS-IS location beacon comment text")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								op.add_option("-d","--delay",action="store",type="int",dest="delay",help="Delay between polls of KML feed")
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 22:23:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								op.add_option("--genpass",action="store_true",dest="genpass",help="Generate the correct passcode for the SSID given in the configuration, or on the command line, print it, and exit.")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								(opts,args) = op.parse_args()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 22:23:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#Handle term and int signals
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def trapexit(_signo,_stack_frame):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("Exiting.")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sys.exit(0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								signal.signal(signal.SIGTERM,trapexit)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								signal.signal(signal.SIGINT,trapexit)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#This needs to be defined before the load below happens.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Load a configuration file, and try to validate that it is loaded.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def loadConfig(cfile):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									global conf
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf = configparser.ConfigParser()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if conf.read(cfile):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if conf.has_section('General'):
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											print("Loaded configuration: " + cfile)
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return True
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return False
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Handle loading of the configuration file first.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Other command-line options may override things defined in the file.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.config:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if not loadConfig(opts.config):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										print("Can't load configuration: " + opts.config)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sys.exit(1)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								else:	#Default behavior if no file specified.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if not loadConfig(os.path.join("/etc", cf)):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if not loadConfig(os.path.join(os.path.dirname(os.path.abspath(__file__)),cf)):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if not loadConfig(cf):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												print("Can't find configuration: " + cf)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												sys.exit(1)
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								#Allow command-line arguments to override the config file.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.ssid:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['APRS']['SSID'] =		opts.ssid
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.passwd:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['APRS']['Password'] =		str(opts.passwd)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.port:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['APRS']['Port'] =		str(opts.port)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.user:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['inReach']['User'] = 	opts.user
							 
						 
					
						
							
								
									
										
										
										
											2021-03-26 17:47:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								if opts.irpass:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['inReach']['Password'] = 	opts.irpass
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								if opts.url:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['inReach']['URL'] = 	opts.url
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.comment:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['APRS']['Comment'] =	opts.comment
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.delay:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['General']['Period'] =	opts.delay
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 22:23:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#SSID should be standardized to upper-case.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								conf['APRS']['SSID'] = conf['APRS']['SSID'].upper()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Running in passcode generator mode.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.genpass:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("Using SSID: " + conf['APRS']['SSID'])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("The passcode is: " + str(aprslib.passcode(conf['APRS']['SSID'])))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sys.exit(0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Handle the special case where we've specified an IMEI on the command-line
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if opts.imei:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['Devices'] = {}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									conf['Devices'][conf['APRS']['SSID']] = str(opts.imei)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Get the number and call from from the default SSID
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#If we have multiple devices with non-specific ID mapping, we'll make it up
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# from this.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								(Call,SSNum) = re.search('(\w+)-(\d+)$',conf['APRS']['SSID']).groups()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								SSNum = int(SSNum)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								#The beginning of our APRS packets should contain a source, path, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# q construct, and gateway address.  We'll reuse the same SSID as a gate.
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# This is the part between the source and the gate.
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 13:27:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								ARPreamble	= ''.join(['>APRS,','TCPIP*,','qAS,',conf['APRS']['SSID']])
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								NAME		= "iR-APRSISD"
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								REV		= "0.3"
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-26 17:47:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#Set up the handler for HTTP connections
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if conf.has_option('inReach','Password'):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									passman		= urllib.request.HTTPPasswordMgrWithDefaultRealm()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									passman.add_password(None, conf['inReach']['URL'],'',conf['inReach']['Password'])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									httpauth	= urllib.request.HTTPBasicAuthHandler(passman)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									http		= urllib.request.build_opener(httpauth)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								else:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									http		= urllib.request.build_opener()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								urllib.request.install_opener(http)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								#Handle connection to APRS-IS
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def reconnect():
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									global AIS
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									attempt = 1
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									while True:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AIS = aprslib.IS(conf['APRS']['SSID'],passwd=conf['APRS']['Password'],port=conf['APRS']['Port'])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										try:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											AIS.connect()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										except Exception as e:
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											print("Connection failed.  Reconnecting: " + str(attempt))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											attempt += 1
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											time.sleep(3)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#We'll store the device to ssid mapping here.
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								SSIDList = {}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#We'll store timestamps here
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								lastUpdate = {}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#Packet counts here
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								transmitted = {}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Last time stats() was run:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								lastStats = calendar.timegm(time.gmtime())
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#Load any preconfigured mappings
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								if conf.has_section('Devices'):
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									print("Loading predefined SSID mappings.")
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for device in conf['Devices'].keys():
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SSIDList[conf['Devices'][device]] = device.upper()
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										print("Static mapping: " + SSIDList[conf['Devices'][device]] + " -> " + device.upper())
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Get an SSID
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def getSSID(DID):
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									global lastUpdate, SSIDList, transmitted, SSNum, Call
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if not DID:	# Don't map None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return None
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#If we have a Devices section, the SSID list is static.
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if DID not in SSIDList:
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if conf.has_section('Devices'):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return None
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										SSIDList[DID] = ''.join([Call,"-",str(SSNum)])
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										SSNum = SSNum + 1
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										print("Mapping: " + DID + " -> " + SSIDList[DID])
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#Add a timestamp on the first call
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# This prevents us from redelivering an old message, which can stay
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# in the feed.
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if DID not in lastUpdate:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										lastUpdate[DID] = calendar.timegm(time.gmtime())
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if DID not in transmitted:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										transmitted[DID] = 0
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return SSIDList[DID]
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#APRS-IS Setup
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AIS = None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								reconnect()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								#Get information from a Placemark
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def parsePlacemark(Placemark):
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#We only care about the Placemarks with the ExtendedData sections.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if not Placemark.getElementsByTagName('ExtendedData'):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return None
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#Now process the extended data into something easier to handle.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									extended = {}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for xd in Placemark.getElementsByTagName('ExtendedData')[0].getElementsByTagName('Data'):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if not xd.getElementsByTagName('value')[0].firstChild == None:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											extended[xd.getAttribute('name')] = xd.getElementsByTagName('value')[0].firstChild.nodeValue	
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#Make sure the device mapping is good.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if not 'IMEI' in extended:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if not getSSID(extended['IMEI']):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return None
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#Now build the position vector
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									latitude	= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									longitude	= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									elevation	= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									velocity	= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									course		= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uttime		= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									device		= None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IMEI		= extended['IMEI']
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if 'Latitude' in extended and 'Longitude' in extended:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latitude	= float(extended['Latitude'])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										longitude	= float(extended['Longitude'])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if 'Elevation' in extended:
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										#Altitude needs to be in feet above sea-level
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										# what we get instead is a string with a number of meters
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										# at the beginning.
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										elevation       = re.sub(r'^(\d+\.?\d+)\s*m.*',r'\1',extended['Elevation'])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										elevation       = float(elevation) * 3.2808399
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if 'Velocity' in extended:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										#Velocity in knots, according to APRS.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										velocity	= float(re.sub(r'(\d+\.?\d+).*',r'\1', extended['Velocity']))*0.5399568
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if 'Course' in extended:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										#... and the course is just a heading in degrees.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										course		= float(re.sub(r'(\d+\.?\d+).*',r'\1', extended['Course']))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uttime		= time.strptime(extended['Time UTC'] + " UTC","%m/%d/%Y %I:%M:%S %p %Z")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									device		= extended['Device Type']
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#If we have SMS data, add that.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if 'Text' in extended:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										comment = extended['Text']
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else:	#Default comment
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										comment = conf['APRS']['Comment']
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return [device,IMEI,ARPreamble,uttime,latitude,longitude,elevation,course,velocity,comment]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Return a list of all events available.  Each one is a list of arguments
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# for the below sendAPRS function
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def getEvents():
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									events = []
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									try:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										KML = http.open(conf['inReach']['URL']).read()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									except Exception as e:
							 
						 
					
						
							
								
									
										
										
										
											2021-04-01 02:25:09 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										print("Error reading URL: " + conf['inReach']['URL'])
							 
						 
					
						
							
								
									
										
										
										
											2021-04-06 18:39:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return events
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									try:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data = xml.dom.minidom.parseString(KML).documentElement
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									except Exception as e:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										print("Can't process KML feed on this pass.")
							 
						 
					
						
							
								
									
										
										
										
											2021-04-06 18:39:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return events
							 
						 
					
						
							
								
									
										
										
										
											2021-03-29 00:55:29 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									#The first placemark will have the expanded current location information.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for PM in data.getElementsByTagName('Placemark'):
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										res = parsePlacemark(PM)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if res:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											events.append(res)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return events
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#Compile and send an APRS packet from the given information
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#According to spec, one valid format for location beacons is
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# @092345z/4903.50N/07201.75W>088/036
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# with a comment on the end that can include altitude and other
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# information.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Arguments are:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#	Device type, Device ID, APRS Preamble, struct Timestamp, float Latitude
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#	float Longitude, float Altitude in feet, int float course in degrees,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#	float speed in knots, comment
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def sendAPRS(device, DevID, ARPreamble, tstamp, lat, long, alt, course, speed, comment):
							 
						 
					
						
							
								
									
										
										
										
											2021-04-06 12:27:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									global		conf, transmitted, lastUpdate
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									etime		= calendar.timegm(tstamp)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#Latitude conversion
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#We start with the truncated degrees, filled to two places
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# then add fractional minutes two 2x2 digits.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slat		= str(abs(math.trunc(lat))).zfill(2)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slat		+= '{:.02f}'.format(round((abs(lat)-abs(math.trunc(lat)))*60,2)).zfill(5)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if lat > 0:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slat += "N"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slat += "S"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#Longitude        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slong	= str(abs(math.trunc(long))).zfill(3)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									slong	+= '{:.02f}'.format(round((abs(long)-abs(math.trunc(long)))*60,2)).zfill(5)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if long > 0:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slong += "E"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										slong += "W"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pos		= ''.join([slat,conf['APRS']['Separator'],slong,conf['APRS']['Symbol']])
							 
						 
					
						
							
								
									
										
										
										
											2021-04-02 19:22:21 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									gateInfo	= ''.join([" : ", NAME, " v", REV, " : ", platform.system(), " on ", platform.machine(), " : "])
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if device:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										gateInfo = gateInfo + device
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#In the format we're using, APRS comments can be 36 characters
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# ... but APRS-IS doesn't seem to care, so leave this off.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#comment	= comment[:36]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									aprsPacket	= ''.join([getSSID(DevID),ARPreamble, ':@', time.strftime("%d%H%Mz",tstamp), pos]) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#Check to make sure the update is new:
							 
						 
					
						
							
								
									
										
										
										
											2021-04-06 18:39:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if not etime > lastUpdate[DevID]:
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return None
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#In theory a course/speed of 000/000 sholdn't be much different
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# from not reporting one, but also in theory, more space is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# available for a comment if we don't add the data extension.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if speed and course:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aprsPacket	= ''.join([aprsPacket,str(round(course)).zfill(3), '/', str(min(round(speed),999)).zfill(3)])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#Same with altitude:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if alt:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										#We need six digits of altitude.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aprsPacket	= aprsPacket + "/A=" + str(round(alt)).zfill(6)[0:6]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									# Regardless:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									aprsPacket		= aprsPacket + comment + gateInfo
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									try:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										aprslib.parse(aprsPacket)	# For syntax
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										AIS.sendall(aprsPacket)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									except Exception as e:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										print("Could not send APRS packet: ")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										print(aprsPacket)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										print("Attempting reconnect just in case.")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reconnect()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pass
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									#Last update in UTC
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									lastUpdate[DevID]	= calendar.timegm(tstamp)
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									transmitted[DevID]	+= 1
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def stats():
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									global transmitted, lastStats
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									lastStats = calendar.timegm(time.gmtime())
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("----------------Packet Forwarding Summary----------------")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("|\t" + time.strftime("%Y-%m-%d %R",time.localtime()))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("| SSID		DevID			Packets forwarded")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for device in transmitted:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										print("| " + getSSID(device) + "\t" + device + "\t\t" + str(transmitted[device]))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print("---------------------------------------------------------")
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									print()
							 
						 
					
						
							
								
									
										
										
										
											2021-03-31 22:20:25 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#... and here is the main loop.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								while True:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for packet in getEvents():
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sendAPRS(*packet)	#Otherwise a list of sendAPRS args for the next packet to send.
							 
						 
					
						
							
								
									
										
										
										
											2021-04-03 14:02:46 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if "Logstats" in conf["General"]:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if calendar.timegm(time.gmtime()) > lastStats + conf.getint("General","Logstats"):
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											stats()
							 
						 
					
						
							
								
									
										
										
										
											2021-03-25 21:03:37 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									time.sleep(conf.getfloat('General','Period'))