Merge branch 'dev', v0.6.29

004b171 - bump to v0.6.29
0e05efe - catch ValueError when decoding lat/lng for MicE
0d80f20 - add underscore as valid char for message addresse
4b1dad5 - improved and expanded logging in IS class
cffc721 - minor code clean up in IS class
0026655 - improve I/O waiting using select
This commit is contained in:
Rossen Georgiev 2014-12-26 15:03:19 +00:00
commit 7a2c245e91
3 changed files with 49 additions and 46 deletions

View File

@ -19,6 +19,7 @@
IS class is used for connection to APRS-IS network
"""
import socket
import select
import time
import logging
import sys
@ -62,17 +63,6 @@ class IS(object):
self._connected = False
self.buf = ''
def callsign_filter(self, callsigns):
"""
Sets a filter for the specified callsigns.
Only those will be sent to us by the server
"""
if type(callsigns) is not list or len(callsigns) == 0:
return False
return self.set_filter("b/%s" % "/".join(callsigns))
def set_filter(self, filter_text):
"""
Set a specified aprs-is filter for this connection
@ -84,8 +74,6 @@ class IS(object):
if self._connected:
self.sock.sendall("#filter %s\r\n" % self.filter)
return True
def set_login(self, callsign, passwd):
"""
Set callsign and password
@ -104,28 +92,19 @@ class IS(object):
Initiate connection to APRS server and attempt to login
"""
if not self._connected:
while True:
try:
self.logger.info("Attempting connection to %s:%s", self.server[0], self.server[1])
self._connect()
if self._connected:
return
self.logger.info("Sending login information")
self._send_login()
while True:
try:
self._connect()
self._send_login()
break
except:
if not blocking:
raise
self.logger.info("Filter set to: %s", self.filter)
if self.passwd == "-1":
self.logger.info("Login successful (receive only)")
else:
self.logger.info("Login successful")
break
except:
if not blocking:
raise
time.sleep(30) # attempt to reconnect after 30 seconds
time.sleep(30) # attempt to reconnect after 30 seconds
def close(self):
"""
@ -155,6 +134,8 @@ class IS(object):
if not self._connected:
raise ConnectionError("not connected to a server")
line = ''
while True:
try:
for line in self._socket_readlines(blocking):
@ -163,6 +144,8 @@ class IS(object):
callback(line)
else:
callback(parse(line))
else:
self.logger.debug("Server: %s", line)
except (KeyboardInterrupt, SystemExit):
raise
except (ConnectionDrop, ConnectionError):
@ -189,10 +172,16 @@ class IS(object):
Attemps to open a connection to the server
"""
self.logger.info("Attempting connection to %s:%s", self.server[0], self.server[1])
try:
# 15 seconds connection timeout
self.sock = socket.create_connection(self.server, 15)
raddr, rport = self.sock.getpeername()
self.logger.info("Connected to %s:%s", raddr, rport)
# 5 second timeout to receive server banner
self.sock.setblocking(1)
self.sock.settimeout(5)
@ -207,7 +196,11 @@ class IS(object):
self.sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPINTVL, 5)
# pylint: enable=E1103
if self.sock.recv(512)[0] != "#":
banner = self.sock.recv(512)
if banner[0] == "#":
self.logger.debug("Banner: %s", banner.rstrip())
else:
raise ConnectionError("invalid banner from server")
except Exception, e:
@ -232,10 +225,14 @@ class IS(object):
__version__
)
self.logger.info("Sending login information")
try:
self.sock.sendall(login_str)
self.sock.settimeout(5)
test = self.sock.recv(len(login_str) + 100)
test = self.sock.recv(len(login_str) + 100).rstrip()
self.logger.info("Server: %s", test)
(x, x, callsign, status, x) = test.split(' ', 4)
@ -246,9 +243,14 @@ class IS(object):
if status != "verified," and self.passwd != "-1":
raise LoginError("Password is incorrect")
except LoginError, e:
if self.passwd == "-1":
self.logger.info("Login successful (receive only)")
else:
self.logger.info("Login successful")
except LoginError:
self.close()
raise LoginError("failed to login: %s" % e)
raise
except:
self.close()
raise LoginError("failed to login")
@ -265,8 +267,10 @@ class IS(object):
while True:
short_buf = ''
select.select([self.sock], [], [], None if blocking else 0)
try:
short_buf = self.sock.recv(1024)
short_buf = self.sock.recv(4096)
# sock.recv returns empty if the connection drops
if not short_buf:
@ -285,7 +289,3 @@ class IS(object):
line, self.buf = self.buf.split("\r\n", 1)
yield line
# lets not hog the CPU when there's nothing to do
if blocking:
time.sleep(0.1)

View File

@ -365,7 +365,7 @@ def parse(raw_sentence):
# the while loop is used to easily break out once a match is found
while True:
# try to match bulletin
match = re.findall(r"^BLN([0-9])([a-zA-Z0-9 \-]{5}):(.{0,67})", body)
match = re.findall(r"^BLN([0-9])([a-z0-9_ \-]{5}):(.{0,67})", body, re.I)
if match:
bid, identifier, text = match[0]
identifier = identifier.rstrip(' ')
@ -514,8 +514,11 @@ def parse(raw_sentence):
symbol_table = packet[0]
symbol = packet[9]
latitude = 90 - (base91.to_decimal(packet[1:5]) / 380926.0)
longitude = -180 + (base91.to_decimal(packet[5:9]) / 190463.0)
try:
latitude = 90 - (base91.to_decimal(packet[1:5]) / 380926.0)
longitude = -180 + (base91.to_decimal(packet[5:9]) / 190463.0)
except ValueError:
raise ParseError("invalid characters in latitude/longitude encoding")
# parse csT

View File

@ -1 +1 @@
__version__ = '0.6.28'
__version__ = '0.6.29'