Files
map_generator/main.py

287 lines
9.2 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_STA(sta_txt):
time = int(sta_txt[2:10], 16)
lat = int(sta_txt[10:16], 16)
if lat == 0x800000:
lat = None
lon = None
velocity = None
heading = None
else:
lat = lat * 1.0728837339 * 0.00001 # sirka ve [st.]
lon = int(sta_txt[16:22], 16) * 2.1457672119 * 0.00001 # delka ve [st.]
if lon > 180:
lon = lon - 360
velocity = int(sta_txt[23:25], 16) # rychlost v [km/h]
heading = int(sta_txt[25:27], 16) * 2 # smer ve stupnich 0=Sever
rr = int(sta_txt[27:29], 16)
nsat = rr & 0x3f # Pocet satelitu GNSS
nav = rr >> 6 # Navigace 0=ne, 1=ano, 2=ano+SBAS
alt = int(sta_txt[29:33], 16) # nadm. vyska v [m]
if alt >= 0x8000:
alt = alt - 0x10000
age = expb_expand(int(sta_txt[33:35], 16)) # stari polohy v [s]
ss = int(sta_txt[38:40], 16)
active = ss & 2 == 2 # jednotka detekuje jizdy
pwr = ss & 1 == 1 # jednotka je v napajeni
csq = int(sta_txt[43:44], 16) # kvalita signalu GSM 0-15
return STA(time, lat, lon, velocity, heading, nav, nsat,
alt, age, active, pwr, csq)
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()