Files
map_generator/main.py

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()