-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Faraday-APRS Persistent Across Network Failures #271
Changes from 21 commits
dad1f90
62263c5
5ccd19a
74212a3
eb55358
d132474
0a57a3b
7ead5f3
b82e2fd
161145c
541f10c
e68b408
4db85fb
8eafdf5
041a922
bf2a6f1
0565340
982b169
ffe768d
5c47607
83ae953
799b61f
ac65bd6
b354512
a0e6d73
ddcb2ff
75d6930
f529c01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
from time import sleep | ||
import sys | ||
import argparse | ||
from aprslib import base91 | ||
|
||
from classes import helper | ||
|
||
|
@@ -103,6 +104,11 @@ def aprs_worker(config, sock): | |
# Local variable initialization | ||
telemSequence = 0 | ||
|
||
#dev | ||
sock = '' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: This statement is unnecessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? |
||
sock = connectAPRSIS() | ||
conn = True | ||
|
||
# Start infinite loop to send station data to APRS-IS | ||
while True: | ||
# Query telemetry database for station data | ||
|
@@ -114,11 +120,21 @@ def aprs_worker(config, sock): | |
logger.info(str.format(len(stations))) | ||
|
||
# Iterate through all stations sending telemetry and position data | ||
sendPositions(stationData, sock) | ||
telemSequence = sendtelemetry(stationData, telemSequence, sock) | ||
sendTelemLabels(stationData, sock) | ||
sendParameters(stationData, sock) | ||
sendEquations(stationData, sock) | ||
if not conn: | ||
sock = connectAPRSIS() | ||
try: | ||
conn = sendPositions(telemSequence, stationData, sock) | ||
|
||
# Just send labels, Parameters, and Equations every 10th loop | ||
if telemSequence % 10 == 0: | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Extra blank line. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||
sendTelemLabels(stationData, sock) | ||
sendParameters(stationData, sock) | ||
sendEquations(stationData, sock) | ||
telemSequence += 1 | ||
|
||
except StandardError as e: | ||
logger.error(e) | ||
|
||
# Sleep for intended update rate (seconds) | ||
sleep(rate) | ||
|
@@ -231,10 +247,33 @@ def nmeaToDegDecMin(latitude, longitude): | |
return [latString, lonString] | ||
|
||
|
||
def sendPositions(stations, socket): | ||
def sendAPRSPacket(socket, packet): | ||
""" | ||
Sends an APRS packet (just a string) to the socket specified. If an | ||
error occurs a False is returned while a True is returned if successful. | ||
On an error, the socket is closed as it is no longer useful. | ||
|
||
:param socket: APRS-IS server internet socket | ||
:param packet: String to be sent to APRS-IS | ||
:return: Boolean | ||
""" | ||
|
||
try: | ||
socket.sendall(packet) | ||
return True | ||
|
||
except IOError as e: | ||
logger.error(e) | ||
socket.close() | ||
return False | ||
|
||
|
||
def sendPositions(telemSequence, stations, socket): | ||
""" | ||
Constructs an APRS position string for station and sends to a socket | ||
Constructs an APRS position string for station and sends to a socket. | ||
Includes BASE91 comment telemetry functionality as well. | ||
|
||
:param telemSequence: Telemetry sequence number | ||
:param stations: List of dictionary organized station data | ||
:param socket: APRS-IS server internet socket | ||
:return: None | ||
|
@@ -268,11 +307,37 @@ def sendPositions(stations, socket): | |
altSymbol = aprsConfig.get('APRS', 'ALTSYMBOL') | ||
comment = aprsConfig.get('APRS', 'COMMENT') | ||
altComment = aprsConfig.get('APRS', 'ALTCOMMENT') | ||
ioSource = aprsConfig.get('APRS', 'IOSOURCE').upper() | ||
|
||
# Create nodes from GPS data | ||
node = sourceCallsign + "-" + str(sourceID) | ||
destNode = destinationCallsign + "-" + str(destinationID) | ||
|
||
#Obtain GPIO data | ||
gpioValues = station["GPIOSTATE"] | ||
rfValues = station["RFSTATE"] | ||
|
||
# Extract IO data | ||
if ioSource == 'GPIO': | ||
ioList = gpioValues | ||
elif ioSource == 'RF': | ||
ioList = rfValues | ||
|
||
# Generate BASE91 telemetry with aprslib using a width of 2 | ||
b91seq = base91.from_decimal(telemSequence, 2) | ||
b91a = base91.from_decimal(station["ADC0"], 2) | ||
b91b = base91.from_decimal(station["ADC1"], 2) | ||
b91c = base91.from_decimal(station["ADC3"], 2) | ||
b91d = base91.from_decimal(station["ADC6"], 2) | ||
b91e = base91.from_decimal(station["BOARDTEMP"], 2) | ||
b91f = base91.from_decimal(ioList, 2) | ||
|
||
b91Tlm = "|{0}{1}{2}{3}{4}{5}{6}|".format(b91seq, b91a, b91b, b91c, b91d, b91e, b91f) | ||
|
||
# add telemetry to comments | ||
comment = comment + b91Tlm | ||
altComment = altComment + b91Tlm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated |
||
|
||
# Convert position to APRS-IS compliant string | ||
latString, lonString = nmeaToDegDecMin(latitude, longitude) | ||
|
||
|
@@ -317,11 +382,8 @@ def sendPositions(stations, socket): | |
|
||
logger.debug(positionString) | ||
|
||
try: | ||
socket.sendall(positionString) | ||
|
||
except IOError as e: | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, positionString) | ||
return status | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Here and below. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All |
||
|
||
elif node == destNode: | ||
# APRS string is for local node | ||
|
@@ -342,12 +404,8 @@ def sendPositions(stations, socket): | |
altComment) | ||
logger.debug(positionString) | ||
|
||
try: | ||
socket.sendall(positionString) | ||
|
||
except IOError as e: | ||
logger.error("SendPosition") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, positionString) | ||
return status | ||
|
||
|
||
def sendtelemetry(stations, telemSequence, socket): | ||
|
@@ -403,12 +461,8 @@ def sendtelemetry(stations, telemSequence, socket): | |
|
||
logger.debug(telemetry) | ||
|
||
try: | ||
socket.sendall(telemetry) | ||
|
||
except IOError as e: | ||
logger.error("SendTelemetry") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, telemetry) | ||
return status | ||
|
||
elif node == destNode: | ||
# APRS string is for local node | ||
|
@@ -425,12 +479,8 @@ def sendtelemetry(stations, telemSequence, socket): | |
|
||
logger.debug(telemetry) | ||
|
||
try: | ||
socket.sendall(telemetry) | ||
|
||
except IOError as e: | ||
logger.error("Sendtelemetry") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, telemetry) | ||
return status | ||
|
||
# Check for telemetry sequence rollover | ||
if telemSequence >= 999: | ||
|
@@ -493,25 +543,16 @@ def sendTelemLabels(stations, socket): | |
node, destAddress, qConstruct, destNode, node, unitsAndLabels) | ||
logger.debug(labels) | ||
|
||
try: | ||
socket.sendall(labels) | ||
|
||
except IOError as e: | ||
logger.error("SendTelemLabels") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, labels) | ||
return status | ||
|
||
elif node == destNode: | ||
# APRS string is for local node | ||
labels = '{}>{}::{} :UNIT.{}\r'.format( | ||
node, destAddress, node, unitsAndLabels) | ||
|
||
logger.debug(labels) | ||
try: | ||
socket.sendall(labels) | ||
|
||
except IOError as e: | ||
logger.error("SendTelemLabels") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, labels) | ||
return status | ||
|
||
|
||
def sendParameters(stations, socket): | ||
|
@@ -564,26 +605,16 @@ def sendParameters(stations, socket): | |
parameters = '{}>{},{},{}::{} :PARM.{}\r'.format( | ||
node, destAddress, qConstruct, destNode, node, adcAndIoParams) | ||
|
||
logger.debug(parameters) | ||
try: | ||
socket.sendall(parameters) | ||
|
||
except IOError as e: | ||
logger.error("SendParameters") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, parameters) | ||
return status | ||
|
||
elif node == destNode: | ||
# APRS string is for local node | ||
parameters = '{}>{}::{} :PARM.{}\r'.format( | ||
node, destAddress, node, adcAndIoParams) | ||
|
||
logger.debug(parameters) | ||
try: | ||
socket.sendall(parameters) | ||
|
||
except IOError as e: | ||
logger.error("SendParameters") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, parameters) | ||
return status | ||
|
||
|
||
def sendEquations(stations, socket): | ||
|
@@ -636,26 +667,16 @@ def sendEquations(stations, socket): | |
equations = '{}>{},{},{}::{} :EQNS.{}\r'.format( | ||
node, destAddress, qConstruct, destNode, node, equationConfig) | ||
|
||
logger.debug(equations) | ||
try: | ||
socket.sendall(equations) | ||
|
||
except IOError as e: | ||
logger.error("SendEquations") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, equations) | ||
return status | ||
|
||
elif node == destNode: | ||
# APRS string is for local node | ||
equations = '{}>{}::{} :EQNS.{}\r'.format( | ||
node, destAddress, node, equationConfig) | ||
|
||
logger.debug(equations) | ||
try: | ||
socket.sendall(equations) | ||
|
||
except IOError as e: | ||
logger.error("SendEquations") | ||
logger.error(e) | ||
status = sendAPRSPacket(socket, equations) | ||
return status | ||
|
||
|
||
def connectAPRSIS(): | ||
|
@@ -693,14 +714,17 @@ def connectAPRSIS(): | |
aprssock.sendall(logon_string) | ||
|
||
except IOError as e: | ||
# Close socket and setup for next connection attempt | ||
logger.error(e) | ||
aprssock.close() | ||
aprssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
|
||
else: | ||
logger.info("Connection successful!") | ||
return aprssock | ||
break | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not this change, but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||
|
||
sleep(10) # Try to reconnect every 10 seconds | ||
sleep(2) # Try to reconnect every 10 seconds | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated |
||
return aprssock | ||
else: | ||
while True: | ||
|
@@ -762,7 +786,8 @@ def main(): | |
""" | ||
|
||
logger.info('Starting Faraday APRS-IS application') | ||
sock = connectAPRSIS() | ||
#sock = connectAPRSIS() | ||
sock = '' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I used to need this but with the current implementation of the socket connections I do not. Removed! |
||
|
||
# Initialize local variables | ||
threads = [] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed,
conn=False
now used in the initialization just above to force it to initialize on first loop. Thanks for catching this!