Skip to content

Instantly share code, notes, and snippets.

@code-shoily
Last active December 31, 2015 20:38
Show Gist options
  • Save code-shoily/8041148 to your computer and use it in GitHub Desktop.
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.
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