255 lines
8.1 KiB
Python
255 lines
8.1 KiB
Python
import threading
|
|
import sys
|
|
import os
|
|
import logging
|
|
import time
|
|
import socket
|
|
import struct
|
|
import zlib
|
|
import binascii
|
|
from collections import namedtuple
|
|
import csv
|
|
from time import gmtime, strftime
|
|
import reverse_geocoder as rg
|
|
from datetime import datetime, timezone
|
|
import pytz
|
|
from binascii import unhexlify
|
|
import struct
|
|
|
|
SOCK_BUFF_SIZE = 100000
|
|
|
|
global dictionary
|
|
dictionary = {}
|
|
helper = {}
|
|
|
|
# This is dictionary to be able to convert OBUID to unitID
|
|
#TODO: This needs to be updated regularly
|
|
|
|
with open('/var/www/html/certificates.princip.cz/mapa/data/unitinfo.csv', 'r') as file:
|
|
reader = csv.reader(file)
|
|
for row in reader:
|
|
print(row[0])
|
|
print(row[1])
|
|
helper[int(row[0])] = {'obuid': row[1]}
|
|
|
|
|
|
STA = namedtuple('STA', ['time', 'lat', 'lon', 'velocity', 'heading', 'nav',
|
|
'nsat', 'alt', 'age', 'active', 'pwr', 'csq'])
|
|
|
|
|
|
def expb_expand(x):
|
|
if x <= 32:
|
|
return x
|
|
return ((x & 0x0f) + 0x10) << ((x >> 4) - 1)
|
|
|
|
|
|
def convert_STA2(data):
|
|
data = unhexlify(data)
|
|
|
|
class Struct:
|
|
pass
|
|
|
|
self = Struct()
|
|
|
|
body = struct.unpack('>ixxxxxxBBBHBBBBBBBBBBBBxxxxxxH', data)
|
|
|
|
self.time = body[0]
|
|
self.lat = struct.unpack(">i", data[4:8])[0] >> 8
|
|
self.lon = struct.unpack(">i", data[7:11])[0] >> 8
|
|
self.speed = body[1]
|
|
self.heading = body[2]
|
|
self.nav = body[3] / 0x40
|
|
self.nsat = body[3] % 0x40
|
|
self.alt = body[4]
|
|
# self.age = expand_expb(body[5])
|
|
|
|
self.guarding_state = body[6]
|
|
self.guarding_input = body[7]
|
|
self.runlevel = body[8] >> 4
|
|
self.gsm_state = body[8] & 0x0f
|
|
self.gsm_state2 = body[9] >> 4
|
|
self.csq = body[9] & 0x0f
|
|
|
|
self.reserved0 = body[10]
|
|
self.adc_uin = body[11]
|
|
self.adc_an1 = body[12]
|
|
self.adc_an2 = body[13]
|
|
self.adc_an3 = body[14]
|
|
self.adc_an4 = body[15]
|
|
self.type_of_id = body[16]
|
|
self.driver = data[27:33]
|
|
self.fw_ind = body[17]
|
|
|
|
if self.lat == -0x800000:
|
|
self.lat = None
|
|
self.lon = None
|
|
else:
|
|
self.lat = self.lat * 1.0728837339e-5
|
|
self.lon = self.lon * 2.1457672119e-5
|
|
|
|
if self.heading == 255:
|
|
self.heading = None
|
|
else:
|
|
self.heading *= 2
|
|
|
|
print(self.lat, self.lon, self.time,self.speed, self.heading, self.nav, self.nsat, self.alt, self.guarding_state, self.guarding_input, self.runlevel, self.gsm_state, self.gsm_state2, self.csq, self.reserved0, self.adc_uin, self.adc_an1, self.adc_an2, self.adc_an3, self.adc_an4, self.type_of_id, self.driver, self.fw_ind)
|
|
return self.lat, self.lon, self.time, self.speed, self.heading, self.nav, self.nsat, self.alt, self.guarding_state, self.guarding_input, self.runlevel, self.gsm_state, self.gsm_state2, self.csq, self.reserved0, self.adc_uin, self.adc_an1, self.adc_an2, self.adc_an3, self.adc_an4, self.type_of_id, self.driver, self.fw_ind
|
|
|
|
|
|
def generateMap():
|
|
time.sleep(60)
|
|
while True:
|
|
start_time = time.time()
|
|
with open('/var/www/html/maps.princip.cz/map5/data/testmapdata.csv', 'w') as f:
|
|
f.write("lat|lng|Name|SN|Unit time|STA received|Lat|Lon|Country|Velocity|Heading|Nav|Nsat|Age|Active|Pwr|Csq|sta\n")
|
|
print(f"generateMap func initialized")
|
|
print("Count of units: ", len(dictionary.keys()))
|
|
|
|
|
|
# Copy of dict, the original one is modified during the loop
|
|
dictionary_print = dictionary.copy()
|
|
for key in dictionary_print.keys():
|
|
# Gather all needed data
|
|
|
|
# Get the actual OBUID from helper
|
|
|
|
print(helper[1]['obuid'])
|
|
if key in helper:
|
|
obuid = helper[key]['obuid']
|
|
|
|
print("in helper")
|
|
else:
|
|
obuid = "N/A"
|
|
|
|
print("not in helper")
|
|
|
|
|
|
msgtype = dictionary[key]['msgtype']
|
|
payload = dictionary[key]['payload']
|
|
|
|
datasta = convert_STA2(payload)#datasta = convert_STA(payload)
|
|
|
|
print("datasta: ", datasta)
|
|
|
|
|
|
# Parse unittime
|
|
if datasta is not None:
|
|
print(datasta)
|
|
if datasta[0] is not None and datasta[0] is not "0":
|
|
timefromsta = int(datasta[0])
|
|
tz = pytz.timezone("Europe/Prague")
|
|
timefromsta = datetime.fromtimestamp(timefromsta, tz)
|
|
timefromsta = timefromsta.strftime("%Y-%m-%d %H:%M:%S")
|
|
else:
|
|
break
|
|
|
|
|
|
|
|
if datasta[1] is not None:
|
|
pass
|
|
else:
|
|
break
|
|
lat = datasta[1]
|
|
lon = datasta[2]
|
|
velocity = datasta[3]
|
|
heading = datasta[4]
|
|
nav = datasta[5]
|
|
nsat = datasta[6]
|
|
alt = datasta[7]
|
|
age = datasta[8]
|
|
active = datasta[9]
|
|
pwr = datasta[10]
|
|
csq = datasta[11]
|
|
|
|
# Real time we got the STA
|
|
rtime = datetime.now(tz)
|
|
rtime = rtime.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
# Get the state from location
|
|
coordinates = (lat, lon)
|
|
if datasta[1] and datasta[2] is not None:
|
|
results = rg.search(coordinates, mode=1)
|
|
country = results[0]['cc']
|
|
# And finally just feed the file
|
|
|
|
|
|
f.write(f"{lat}|{lon}|{obuid}|{msgtype}|{timefromsta}|{rtime}|{lat}|{lon}|{country}|{velocity}|{heading}|{nav}|{nsat}|{alt}|{age}|{active}|{pwr}|{csq}|{payload}\n")
|
|
|
|
|
|
# TODO: needs rewrite to trigger this function on request
|
|
print("--- %s seconds ---" % (time.time() - start_time))
|
|
time.sleep(60)
|
|
|
|
|
|
def main():
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
class YArgumentParser(ArgumentParser):
|
|
def format_help(self):
|
|
return ArgumentParser.format_help(self) + \
|
|
getattr(self, "help_tail", "")
|
|
|
|
parser = YArgumentParser(usage="", epilog="")
|
|
|
|
parser.add_argument("-a", "--ip-addr", type=str, default="192.168.8.11",
|
|
help="")
|
|
parser.add_argument("-p", "--ip-port", type=int, default=5001,
|
|
help="")
|
|
parser.add_argument("-l", "--log-level", type=int, default=20,
|
|
help="Logging level")
|
|
parser.help_tail = """
|
|
Example:
|
|
python script.py -f file ???
|
|
"""
|
|
|
|
setup = parser.parse_args()
|
|
|
|
logging.basicConfig(stream=sys.stderr, level=setup.log_level)
|
|
logging.root.setLevel(setup.log_level)
|
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
sock.bind((setup.ip_addr, setup.ip_port))
|
|
|
|
thread_generateMap = threading.Thread(name=generateMap,target=generateMap)
|
|
thread_generateMap.start()
|
|
|
|
while True:
|
|
print(f"Waiting for data")
|
|
pack_compress, addr = sock.recvfrom(SOCK_BUFF_SIZE)
|
|
pack = zlib.decompress(pack_compress)
|
|
|
|
while len(pack) > 0:
|
|
size, obuid, msg_type = struct.unpack(">HIb", pack[:7])
|
|
pack = pack[7:]
|
|
payload = pack[:size]
|
|
pack = pack[size:]
|
|
|
|
#print("obuid:{} >{}{}".format(obuid, chr(msg_type), binascii.hexlify(payload)))
|
|
|
|
|
|
tz = pytz.timezone("Europe/Prague")
|
|
rdatetime = datetime.now(tz)
|
|
rtime = rdatetime.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
if obuid not in dictionary:
|
|
|
|
#print(f"Creating dictionary for {obuid}")
|
|
dictionary[obuid] = {'msgtype': chr(msg_type), 'payload': binascii.hexlify(payload), 'rtime': rtime}
|
|
|
|
else:
|
|
#print(f"we already have this unit, just update the data")
|
|
dictionary[obuid]["msgtype"] = chr(msg_type)
|
|
dictionary[obuid]["payload"] = binascii.hexlify(payload)
|
|
dictionary[obuid]["rtime"] = rtime
|
|
|
|
|
|
|
|
#obuid: 2409 > Ab
|
|
#'62c04b4647352b0ab781071e0400de7c00014b7b00c3ff0000000e3031354c4330722f'
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main() |