Merge pull request #14 from Meisterschueler/dev

Logger
pull/8/head
Meisterschueler 2015-11-23 21:46:20 +01:00
commit 9d5647ff93
7 zmienionych plików z 66 dodań i 27 usunięć

Wyświetl plik

@ -34,3 +34,10 @@ def createTimestamp(hhmmss, reference):
elif abs(reference.hour - hh) > 1:
raise Exception("Time difference is too big. Reference time:%s - timestamp:%s" % (reference, hhmmss))
return datetime(reference.year, reference.month, reference.day, hh, mm, ss)
def create_aprs_login(user_name, pass_code, app_name, app_version, aprs_filter=None):
if not aprs_filter:
return "user %s pass %s vers %s %s\n" % (user_name, pass_code, app_name, app_version)
else:
return "user %s pass %s vers %s %s filter %s\n" % (user_name, pass_code, app_name, app_version, aprs_filter)

Wyświetl plik

@ -4,14 +4,14 @@ from time import time
from ogn.gateway import settings
from ogn.commands.dbutils import session
from ogn.aprs_parser import parse_aprs
from ogn.aprs_utils import create_aprs_login
from ogn.exceptions import AprsParseError, OgnParseError
from ogn.logger import logger
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from ogn.model import Base
MODULE_VERSION = "0.1"
class ognGateway:
def __init__(self):
@ -21,27 +21,25 @@ class ognGateway:
self.session = session
def connect(self, aprs_user):
if len(aprs_user) < 3 or len(aprs_user) > 9:
print("aprs_user must be a string of 3-9 characters")
# create socket, connect to server, login and make a file object associated with the socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
self.sock.connect((settings.APRS_SERVER_HOST, settings.APRS_SERVER_PORT))
login = 'user %s pass %s vers ogn-gateway-python %s %s\n' % (aprs_user, settings.APRS_PASSCODE, MODULE_VERSION, settings.APRS_FILTER)
login = create_aprs_login(aprs_user, -1, settings.APRS_APP_NAME, settings.APRS_APP_VER, settings.APRS_FILTER)
self.sock.send(login.encode())
self.sock_file = self.sock.makefile('rw')
def disconnect(self):
# close everything
print('Close socket')
self.sock.shutdown(0)
self.sock.close()
def run(self):
keepalive_time = time()
while True:
if time() - keepalive_time > 60:
if time() - keepalive_time > settings.APRS_KEEPALIVE_TIME:
logger.debug('Sending keepalive')
self.sock.send("#keepalive".encode())
keepalive_time = time()
@ -51,7 +49,7 @@ class ognGateway:
# A zero length line should not be return if keepalives are being sent
# A zero length line will only be returned after ~30m if keepalives are not sent
if len(packet_str) == 0:
print('Read returns zero length string. Failure. Orderly closeout')
logger.warning('Read returns zero length string. Failure. Orderly closeout')
break
self.proceed_line(packet_str)
@ -59,12 +57,11 @@ class ognGateway:
def proceed_line(self, line):
try:
beacon = parse_aprs(line)
except AprsParseError as e:
print(e.message)
except AprsParseError:
logger.error('AprsParseError', exc_info=True)
return
except OgnParseError as e:
print(e.message)
print("APRS line: %s" % line)
except OgnParseError:
logger.error('OgnParseError', exc_info=True)
return
if beacon is not None:

Wyświetl plik

@ -1,6 +1,7 @@
import socket
from ogn.gateway import ognGateway
from ogn.logger import logger
DB_URI = 'sqlite:///beacons.db'
@ -11,29 +12,37 @@ manager = Manager()
@manager.command
def run(aprs_user="anon-dev"):
"""Run the aprs client."""
if len(aprs_user) < 3 or len(aprs_user) > 9:
print("aprs_user must be a string of 3-9 characters")
return
user_interrupted = False
gateway = ognGateway()
print("Connect to DB")
logger.info('Connect to DB')
gateway.connect_db()
while user_interrupted is False:
print("Connect OGN gateway as {}".format(aprs_user))
logger.info("Connect OGN gateway as {}".format(aprs_user))
gateway.connect(aprs_user)
socket_open = True
try:
logger.info('Run gateway')
gateway.run()
except KeyboardInterrupt:
print("User interrupted")
logger.error('User interrupted', exc_info=True)
user_interrupted = True
except BrokenPipeError:
print("BrokenPipeError")
logger.error('BrokenPipeError', exc_info=True)
except socket.error:
print("socket error")
socket_open = False
logger.error('Socket error', exc_info=True)
if socket_open:
try:
logger.info('Close socket')
gateway.disconnect()
except OSError as e:
print('Socket close error: {}'.format(e.strerror))
logger.error('Socket close error', exc_info=True)
print("\nExit OGN gateway")

Wyświetl plik

@ -1,6 +1,7 @@
APRS_SERVER_HOST = 'aprs.glidernet.org'
APRS_SERVER_PORT = 14580
APRS_USER = 'PyGrabber'
APRS_PASSCODE = -1 # Read only
APRS_APP_NAME = 'ogn-gateway-python'
APRS_APP_VER = '0.2'
APRS_FILTER = "filter r/+50.0000/+10.0000/5000"
APRS_FILTER = 'r/50.0000/10.0000/5000'
APRS_KEEPALIVE_TIME = 240

17
ogn/logger.py 100644
Wyświetl plik

@ -0,0 +1,17 @@
import logging
logger = logging.getLogger('main')
logger.setLevel(logging.DEBUG)
filehandler = logging.FileHandler('main.log')
filehandler.setLevel(logging.DEBUG)
consolehandler = logging.StreamHandler()
consolehandler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname).4s - %(name)s - %(message)s")
filehandler.setFormatter(formatter)
consolehandler.setFormatter(formatter)
logger.addHandler(filehandler)
logger.addHandler(consolehandler)

Wyświetl plik

@ -10,7 +10,7 @@ class GatewayTest(unittest.TestCase):
# try simple user interrupt
@mock.patch('ogn.gateway.manage.ognGateway')
def test_user_interruption(self, mock_gateway):
def test_run_user_interruption(self, mock_gateway):
instance = mock_gateway.return_value
instance.run.side_effect = KeyboardInterrupt()
@ -23,7 +23,7 @@ class GatewayTest(unittest.TestCase):
# make BrokenPipeErrors and a socket error (may happen) and then a user interrupt (important!)
@mock.patch('ogn.gateway.manage.ognGateway')
def test_BrokenPipeError(self, mock_gateway):
def test_run_multiple_errors(self, mock_gateway):
instance = mock_gateway.return_value
instance.run.side_effect = [BrokenPipeError(), socket.error(), KeyboardInterrupt()]
@ -32,7 +32,7 @@ class GatewayTest(unittest.TestCase):
instance.connect_db.assert_called_once_with()
self.assertEqual(instance.connect.call_count, 3)
self.assertEqual(instance.run.call_count, 3)
self.assertEqual(instance.disconnect.call_count, 2) # not called if socket crashed
self.assertEqual(instance.disconnect.call_count, 3)
if __name__ == '__main__':
unittest.main()

Wyświetl plik

@ -1,7 +1,7 @@
import unittest
from datetime import datetime
from ogn.aprs_utils import dmsToDeg, createTimestamp
from ogn.aprs_utils import dmsToDeg, createTimestamp, create_aprs_login
class TestStringMethods(unittest.TestCase):
@ -21,5 +21,13 @@ class TestStringMethods(unittest.TestCase):
with self.assertRaises(Exception):
createTimestamp(datetime(2015, 10, 15, 23, 59, 59), '123456')
def test_create_aprs_login(self):
basic_login = create_aprs_login('klaus', -1, 'myApp', '0.1')
self.assertEqual('user klaus pass -1 vers myApp 0.1\n', basic_login)
login_with_filter = create_aprs_login('klaus', -1, 'myApp', '0.1', 'r/48.0/11.0/100')
self.assertEqual('user klaus pass -1 vers myApp 0.1 filter r/48.0/11.0/100\n', login_with_filter)
if __name__ == '__main__':
unittest.main()