Last active
December 31, 2015 20:38
-
-
Save code-shoily/8041148 to your computer and use it in GitHub Desktop.
Twisted version of a much more featured Netty Server I coded a couple of years back. Going to separate out the parsers and Mongofy the DB.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import string | |
import simplejson | |
from twisted.internet import protocol, reactor | |
from twisted.protocols.basic import LineReceiver | |
from twisted.enterprise import adbapi | |
from twisted.python import log | |
TABLE = 'raw_data' | |
PORT = 9781 | |
RND = True | |
DB = RND or False | |
sanitize_string = lambda s: ''.join(filter(lambda x:x in string.printable, s)) | |
def longitude(lng): | |
return float(lng[:3]) + float(lng[3:])/60. | |
def latitude(lat): | |
return float(lat[:2]) + float(lat[2:])/60. | |
def parseLocalDeviceFormat(raw_data): | |
try: | |
data_ = filter(None, raw_data.split(",")) | |
output = { | |
"number": data_[0].split("#")[0], | |
"gpstat": data_[1], | |
"lat": latitude(data_[2]), | |
"lat_dir": data_[3], | |
"lng": longitude(data_[4]), | |
"lng_dir": data_[5], | |
"speed": data_[6], | |
"bearing": data_[7], | |
"io_state": data_[8].split("|")[1], | |
"mileage_flag": "", | |
"mileage": "", | |
"raw_data": raw_data, | |
} | |
except Exception: | |
output = {} | |
return output | |
def insertInfo(result, db, data): | |
if result: | |
try: | |
table = result[0][0] | |
db.runOperation( # Y u no use postgis? | |
"""insert into {} (speed, course, status, lat, lng, | |
sysdatetime, io_state, mileage_flag, | |
mileage, raw_data, is_valid) | |
values ({}, {}, '{}', {}, {}, now(), '{}', '{}', '{}', '{}', true) | |
""".format( | |
table, float(data["speed"]) * 1.852, data["bearing"], data["gpstat"], data["lat"], | |
data["lng"], data["io_state"], data["mileage_flag"], data["mileage"], | |
data["raw_data"])) | |
except Exception: | |
log("Exception for {}: Table not found".format(data["number"])) | |
else: | |
log.msg("TABLE NOT FOUND: PATCHING TO RND TABLE") | |
db.runOperation( | |
"insert into {}(timestamp, data, port) values (now(), '{}', {})".format( | |
TABLE, | |
simplejson.dumps(data), | |
PORT)) | |
def getTable(db, data): | |
result = [] | |
try: | |
db.runQuery("""select related_table from asset_asset | |
where | |
device_id = (select id from inhouse_device where number='{}' | |
limit 1) | |
""".format(data["number"])).addCallback(insertInfo, db, data) | |
except Exception: | |
result = [] | |
return result | |
def parseData(raw_data): | |
""" | |
If there are multiple devices, then inspect the data | |
and select the appropriate parseXXXDeviceFormat function. | |
""" | |
return parseLocalDeviceFormat(raw_data) | |
class GPSD(LineReceiver): | |
def __init__(self, factory): | |
self.factory = factory | |
self.setRawMode() | |
def connectionMade(self): | |
log.msg("Connection made") | |
def rawDataReceived(self, data): | |
self.factory.connections += 1 | |
# log.msg(data) | |
raw_data = sanitize_string(data).strip() | |
self.transport.loseConnection() | |
if not raw_data: return | |
log.msg("[{}] {}".format(self.factory.connections, raw_data)) | |
data = parseData(raw_data) | |
#log.msg("TABLE: %s"%repr(getTable(self.factory.dbpool, data["number"]))) | |
#getTable(self.factory.dbpool, data) | |
if not data: | |
self.factory.dbpool.runOperation( | |
"insert into {}(timestamp, data, port) values (now(), '{}', {})".format( | |
TABLE, raw_data, PORT)) | |
else: | |
getTable(self.factory.dbpool, data) | |
def connectionLost(self, reason): | |
log.msg("[{}] Connection closed".format(self.factory.connections)) | |
self.factory.connections -= 1 | |
class GPSDFactory(protocol.Factory): | |
""" | |
Factory server. Holds basic inforation and spawns new protocols of type Echo | |
""" | |
def __init__(self, *args, **kwargs): | |
self.connections = 0 | |
self.dbpool = adbapi.ConnectionPool( | |
"psycopg2", | |
database='vt_gis_db', | |
user='postgres') if DB else None | |
def buildProtocol(self, addr): | |
return GPSD(self) | |
#log.startLogging(open('log_{}.log'.format(PORT), 'w')) | |
#reactor.listenTCP(PORT, GPSDFactory()) | |
#reactor.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment