commit 024eb52a6989f494785514240407bda2f2428db1 Author: fencl Date: Tue Nov 4 13:50:38 2025 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8ffb5bd --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Python +__pycache__ +*.pyc +*.pyo + +# .idea +*.iws +**/.idea/workspace.xml **/.idea/tasks.xml + +# virtual environment +/venv/ + + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..770abb1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,30 @@ +stages: + - buildimage + - checks + - tests + - deploytest + + +variables: + APP_IMAGE: gitlab.princip.cz:4567/$CI_PROJECT_PATH/app-$CI_COMMIT_REF_NAME + + +Build Application (docker) Image: + stage: buildimage + image: docker:git + before_script: + - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN gitlab.princip.cz:4567 + script: + - docker build -t $APP_IMAGE . + - docker push $APP_IMAGE + except: + - tags + + +Static Checks: + stage: checks + image: $APP_IMAGE + before_script: + - pip install flake8 + script: + - make pep8 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7748579 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.9 + +LABEL maintainer="Martin Fencl " + +RUN apt-get update -y && \ + apt-get dist-upgrade -y + +WORKDIR /app +COPY requirements.txt ./ + +RUN pip3 install --upgrade pip && \ + pip3 install -Ur requirements.txt -i https://pypi.princip.cz + +COPY . . + +CMD [ "python", "./app.py" ] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..20b58e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +# Makefile +help: + @echo "Please use 'make ' where is one of" + @echo " clean clean up __pycache__" + @echo " clean-build clean build files and directories" + @echo " mrproper all cleaning jobs" + @echo " pep8 to check PEP 8" + @echo " static-check to check PEP 8 and merge markers" + +clean: + @echo "-------------------" + @echo "Purifying 'pycache'" + @echo "-------------------" + rm -fv **/*.pyc + rm -fv **/*.pyo + +clean-build: + @echo "--------------" + @echo "Cleaning build" + @echo "--------------" + rm -rfv *.egg-info/ + rm -rfv dist/ + +mrproper: clean clean-build + +# pep8: +# @echo "--------------" +# @echo "Checking PEP" +# @echo "--------------" +# @echo "**pycodestyle**" +# pycodestyle . +# +# @echo "--------------" +# @echo "**flake8**" +# flake8 +pep8: + @echo "--------------" + @echo "**flake8**" + @echo "--------------" + flake8 app.py --exclude=migrations + flake8 scripts --exclude=migrations + +# static-check: pep8 merge-markers + diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f30bd7 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ + +# SWMU web +### Swmu project support web tool + +See: https://gitlab.princip.cz/lab/sw/uhura/swmu/-/wikis/home + +
+                                 _____  _    ____  ____   _              _     
+                                /  ___|| |  | |  \/  | | | |            | |    
+                                \ `--. | |  | | .  . | | | |_      _____| |__  
+                                 `--. \| |/\| | |\/| | | | \ \ /\ / / _ \ '_ \ 
+                                /\__/ /\  /\  / |  | | |_| |\ V  V /  __/ |_) |
+                                \____/  \/  \/\_|  |_/\___/  \_/\_/ \___|_.__/
+                                               O         O
+                                                \\     // 
+                                                 \\   //
+                                                  \\ // 
+                                                 /~~~~~\
+                                          ,-------------------,
+                                          | ,---------------, |
+                                          | |               | |
+                                          | |               | |
+                                          | |               | |
+                                          | |               | |
+                                          | |_______________| |
+                                          |___________________|
+                                          |___________________|
+
+ + diff --git a/app.py b/app.py new file mode 100644 index 0000000..9fb267e --- /dev/null +++ b/app.py @@ -0,0 +1,440 @@ +import os +import shutil + +import folium +import pandas as pd +from flask import Flask +from flask import request, render_template +from flask import send_from_directory, url_for, redirect +from werkzeug.utils import secure_filename + +from scripts import create_mulog + +print("version: 1.5") +ASSETS_DIR = os.path.dirname(os.path.abspath(__file__)) +app = Flask(__name__) + +# app.config['SECRET_KEY'] = '^%huYtFd90;90jjj' +# app.config['MULOGS'] = 'static' +app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 10 # 10mb +app.config['MAX_RECOMMENDED_POS'] = 10000 +app.config['UPLOAD_EXTENSIONS'] = ['.log'] +app.config['UPLOAD_PATH'] = 'uploads' +app.config['FILE_NAME'] = app.config['IGN1A'] = None + +questions = [] +counter_files = 0 + + +@app.route('/', methods=['GET', 'POST']) +@app.route("/home", methods=['GET', 'POST']) +def index(): + environment = request.host + clear = False + if request.method == 'POST': + if len(questions) > 20: + del questions[:1] + if request.form['submit_button'] == "Clear": + del questions[:] + return render_template('index_v2.html', questions=questions, + environment=environment, clear=True, + lenquestions=len(questions)) + elif request.form['submit_button'] == "Generate": + if request.form['modes'] == "None": + questions.append({ + 'loglevel': request.form['loglevels'], + 'id32': request.form['start-id32'], + 'number_swmu': request.form['number_of_swmu'], + 'mode': "None", # set default run mode + 'server_host': request.form['server_hosts'], + 'server_port': request.form['server_ports'], + 'start_port': request.form['start_ports'], + 'bt_spontaneous_timeout': request.form[ + 'bt_spontaneous_timeouts'], + 'sigma': request.form['sigmas'], + 'sta': request.form['stas'], + 'sta_pause': request.form['sta_pauses'], + 'ft_delay': request.form['ft_delays'], + 'ft_mode': request.form['ft_modes'], + }) + elif request.form['modes'] == "run": + questions.append({ + 'loglevel': request.form['loglevels'], + 'id32': request.form['start-id32'], + 'number_swmu': request.form[ + 'number_of_swmu'], + 'mode': request.form['modes'], + 'server_host': request.form['server_hosts'], + 'server_port': request.form['server_ports'], + 'start_port': request.form['start_ports'], + 'bt_spontaneous_timeout': request.form[ + 'bt_spontaneous_timeouts'], + 'sigma': request.form['sigmas'], + 'sta': request.form['stas'], + 'sta_pause': request.form['sta_pauses'], + 'ft_delay': request.form['ft_delays'], + 'ft_mode': request.form['ft_modes'], + 'latitude': request.form['latitudes'], + 'longitude': request.form['longitudes'], + 'domain': request.form['domains'], + 'near_by_domain': request.form['near_by_domains'], + 'x01': request.form['x01s'], + 'x01_pause': request.form['x01_pauses'], + 'units_wo_x1a': request.form['units_wo_x1as'], + 'x1a_pause': request.form['x1a_pauses'], + 'x1a_mask': request.form['x1a_masks'], + 'x1a_type': request.form['x1a_types'], + 'x1d': request.form['x1ds'], + 'x1d_pause': request.form['x1d_pauses'], + 'x1d_weight_axles': request.form['x1d_weight_axles'], + + }) + elif request.form['modes'] == "sim": + questions.append({ + 'loglevel': request.form['loglevels'], + 'id32': request.form['start-id32'], + 'number_swmu': request.form[ + 'number_of_swmu'], + 'mode': request.form['modes'], + 'server_host': request.form['server_hosts'], + 'server_port': request.form['server_ports'], + 'start_port': request.form['start_ports'], + 'bt_spontaneous_timeout': request.form[ + 'bt_spontaneous_timeouts'], + 'sigma': request.form['sigmas'], + 'sta': request.form['stas'], + 'sta_pause': request.form['sta_pauses'], + 'ft_delay': request.form['ft_delays'], + 'ft_mode': request.form['ft_modes'], + 'log': request.form['logs'], + 'sim_time_check': request.form['sim_time_checks'], + 'sim_stop': request.form['sim_stops'], + }) + elif request.form['modes'] == "simfast": + questions.append({ + 'loglevel': request.form['loglevels'], + 'id32': request.form['start-id32'], + 'number_swmu': request.form[ + 'number_of_swmu'], + 'mode': request.form['modes'], + 'server_host': request.form['server_hosts'], + 'server_port': request.form['server_ports'], + 'start_port': request.form['start_ports'], + 'bt_spontaneous_timeout': request.form[ + 'bt_spontaneous_timeouts'], + 'sigma': request.form['sigmas'], + 'sta': request.form['stas'], + 'sta_pause': request.form['sta_pauses'], + 'ft_delay': request.form['ft_delays'], + 'ft_mode': request.form['ft_modes'], + 'log': request.form['logs_simfast'], + 'sim_time_check': request.form['sim_time_checks_simfast'], + 'sim_stop': request.form['sim_stops'], + 'simulate_pause': request.form['simulate_pauses'], + }) + return render_template('index_v2.html', questions=questions, + environment=environment, clear=clear, + lenquestions=len(questions)) + + +@app.route('/info') +def info(): + environment = request.host + return render_template('info.html', environment=environment) + + +@app.route('/helpswmu') +def helpswmu(): + environment = request.host + return render_template('helpswmu.html', environment=environment) + + +""" +@app.route('/mulog_read') +def mulog_read(): + environment = request.host + return render_template('mulog_read.html', environment=environment) +""" + + +@app.route('/mulog_read') +def upload_file(): + environment = request.host + # environment_road = f"http://{environment}/uploader" # on local + environment_road = f"https://{environment}/uploader" + max_pos = app.config['MAX_RECOMMENDED_POS'] + files = listdir_nopos(app.config['UPLOAD_PATH']) + max_size = (app.config['MAX_CONTENT_LENGTH']) / (1024 * 1024) # in mb + ign1a = app.config['IGN1A'] + text = warn = "" + mulogt = [] + other_type_ttt = [] + pos_file = {'latitude': [], 'longitude': [], "msg_type": []} + x01 = x04 = x05 = x08 = x09 = x13 = x14 = x25 = x26 = x0b = 0 + x0d = x1a = x1c = x1d = x02 = x10 = x0e = ts_c = pos_c = 0 + if files: + try: + mulog_path = f"{app.config['UPLOAD_PATH']}/{files[0]}" + mulog_data = create_mulog.dir_mulog( + import_dir=mulog_path, sim_time_check=False) + + # (pos, log, ts_, type, pos) + for (count, message, old_ts, message_type, message_type_parse, + message_type_full_parse, list_ts_warning) in mulog_data: + warn = list_ts_warning + if message_type["type"] == b'\x01': + x01 += 1 + elif message_type["type"] == b'\x04': + x04 += 1 + elif message_type["type"] == b'\x05': + x05 += 1 + elif message_type["type"] == b'\x08': + x08 += 1 + elif message_type["type"] == b'\x09': + x09 += 1 + elif message_type["type"] == b'\x13': + x13 += 1 + elif message_type["type"] == b'\x14': + x14 += 1 + elif message_type["type"] == b'\x25': + x25 += 1 + elif message_type["type"] == b'\x26': + x26 += 1 + elif message_type["type"] == b'\x0b': + x0b += 1 + elif message_type["type"] == b'\x0d': + x0d += 1 + elif message_type["type"] == b'\x1a': + x1a += 1 + if ign1a == "False": + keys = [] + key_fast = message_type_full_parse["fastlog"] + for key in key_fast.keys(): + if key == "latitude": + keys.append(key) + elif key == "longitude": + keys.append(key) + if "latitude" and "longitude" in keys: + key_lat = key_fast["latitude"] + key_lon = key_fast["longitude"] + for lat in key_lat: + pos_file["latitude"].append(lat) + for lon in key_lon: + pos_file["longitude"].append(lon) + msg_type = message_type_parse["type"] + pos_file["msg_type"].append(msg_type) + pos_c += 1 + elif message_type["type"] == b'\x1c': + x1c += 1 + elif message_type["type"] == b'\x1d': + x1d += 1 + elif message_type["type"] == b'\x02': + x02 += 1 + elif message_type["type"] == b'\x10': + x10 += 1 + elif message_type["type"] == b'\n': + continue + elif message_type["type"] == b'"': + continue + elif message_type["type"] == b'#': + continue + elif message_type["type"] == b'\x0e': + x0e += 1 + else: + other_type_ttt.append(message_type["type"]) + + if old_ts is not None: + ts_c += 1 + if message_type["type"] != b'\x1a': + if "latitude" in message_type_parse and \ + "longitude" in message_type_parse: + lat = message_type_parse["latitude"] + lon = message_type_parse["longitude"] + msg_type = message_type_parse["type"] + pos_file["latitude"].append(lat) + pos_file["longitude"].append(lon) + pos_file["msg_type"].append(msg_type) + pos_c += 1 + + if not other_type_ttt: + other_type_ttt.append("None") + if pos_file is not []: + header_key = ["latitude", "longitude", "msg_type"] + df = pd.DataFrame(pos_file) + df.to_csv(f"{app.config['UPLOAD_PATH']}" + f"/{files[0]}_pos_file.csv", columns=header_key) + + mulogt.extend([x01, x04, x05, x08, x09, x13, x14, x25, + x26, x0b, x0d, x1a, x1c, x1d, x10, + x0e, other_type_ttt]) + except IOError: + print("Error: File does not appear to exist.") + # remove() + return "Error: File does not appear to exist.", 400 + except ValueError: + remove() + text = f"ValueError: {ValueError}, file deleted" + print(text) + pass + return render_template('mulog_read.html', files=files, + max_size=max_size, environment=environment, + environment_road=environment_road, mulog=mulogt, + ts_c=ts_c, pos_c=pos_c, text=text, warn=warn, + ign1a=ign1a, max_pos=max_pos, + _scheme="https", _external=True) +# don't use use_scheme and _external with local testing + + +@app.route('/uploader', methods=['GET', 'POST']) +def uploader_file(): + if request.method == 'POST': + app.config['IGN1A'] = request.form['ign1a'] + uploaded_file = request.files['file'] + filename = secure_filename(uploaded_file.filename) + app.config['FILE_NAME'] = filename + if filename != '': + file_ext = os.path.splitext(filename)[1] + if file_ext not in app.config['UPLOAD_EXTENSIONS']: + return "Invalid file, supports only .log format", 400 + remove() + uploaded_file.save( + os.path.join(app.config['UPLOAD_PATH'], filename)) + + return redirect( + url_for('upload_file', _scheme="https", _external=True)) +# don't use use_scheme and _external with local testing + + +@app.route('/uploads/') +def upload(filename): + return send_from_directory(app.config['UPLOAD_PATH'], filename) + + +@app.route('/call_remove') +def call_remove(): + remove() + environment = request.host + # environment_road = f"http://{environment}/uploader" # on local + environment_road = f"https://{environment}/uploader" + files = os.listdir(app.config['UPLOAD_PATH']) + max_size = (app.config['MAX_CONTENT_LENGTH']) / (1024 * 1024) # in mb + return render_template('mulog_read.html', files=files, + max_size=max_size, environment=environment, + environment_road=environment_road, mulog=[], + _scheme="https", _external=True) +# don't use use_scheme and _external with local testing + + +@app.route('/call_render') +def call_render(): + file_path = f"{app.config['UPLOAD_PATH']}/" \ + f"{app.config['FILE_NAME']}_pos_file.csv" + file_ = pd.read_csv(file_path) + file_use = file_[["latitude", "longitude"]] + if file_use.empty: + return f"Failed to render {file_path}, file positions empty.", 400 + else: + map_ = folium.Map(location=[file_use.latitude.mean(), + file_use.longitude.mean()], + zoom_start=14, control_scale=True) + i_count = 0 + for _, row in file_use.iterrows(): + + if row['latitude'] == "latitude": + continue + else: + i_count += 1 + lat_lon = f"{i_count}\n{row['latitude']}\n{row['longitude']}" + if i_count == 1: + folium.Marker([row['latitude'], row['longitude']], + popup=f"First position: \n{lat_lon}", + icon=folium.Icon(color="green", + icon="fas fa-truck"), + ).add_to(map_) + elif i_count == len(file_use): + folium.Marker([row['latitude'], row['longitude']], + popup=f"Last position \n{lat_lon}", + icon=folium.Icon(color="red", + icon="fas fa-truck"), + ).add_to(map_) + else: + folium.Marker([row['latitude'], row['longitude']], + popup=f"{lat_lon}\n", + ).add_to(map_) + """ + points = [] + points.append(tuple([row['latitude'], row['longitude']])) + folium.PolyLine(points, color="red",weight=2.5, opacity=1).add_to(map_) + """ + return map_._repr_html_() # https://fontawesome.com/ + + +@app.errorhandler(413) +def too_large(e): + return f"File is too large {e}, maximum is " \ + f"{(app.config['MAX_CONTENT_LENGTH']) / (1024 * 1024)}mb", 413 + + +@app.errorhandler(404) +def not_found(e): + return f"Error: File does not appear to exist, {e}.", 404 + + +@app.errorhandler(500) +def some_error(e): + return f"{e}. Try Clear button", 500 + + +def remove(): + print("deleted") + folder = app.config['UPLOAD_PATH'] + for filename in os.listdir(folder): + file_path = os.path.join(folder, filename) + try: + if os.path.isfile(file_path) or os.path.islink(file_path): + os.unlink(file_path) + elif os.path.isdir(file_path): + shutil.rmtree(file_path) + except Exception as e: + return f"Failed to delete %s. Reason: {(file_path, e)}", 400 + + +def listdir_nopos(path): + r = [] + for _ in os.listdir(path): + if not _.endswith('_pos_file.csv'): + r.append(_) + return r + + +""" +@app.route('/SomeFunction') +def SomeFunction(): + print('In SomeFunction') + return "Nothing" + + +@app.route('/clear') +def SomeFunction2(): + print('In SomeFunction2') + return "Nothing" + + +@app.route('/swmu_run') +def swmu_run(): + os.system( + return "Nothing" +""" + +if __name__ == '__main__': + app.run(debug=True, host="0.0.0.0", port=50002) + """ + app.run(debug=True, host="0.0.0.0", port=5000 2, ssl_context=( + "server.crt", "server.key" + )) + """ + """ + app.run(debug=True, host="0.0.0.0", port=50002, + ssl_context=('cert/cert.pem', 'cert/key.pem') + ) + """ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..fadb3f1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +version: "3.9" + +services: + + swmu: + image: registry.martinfencl.eu/swmu_web:ver1.3 + + ports: + - 8046:50002 \ No newline at end of file diff --git a/help.md b/help.md new file mode 100644 index 0000000..eda940b --- /dev/null +++ b/help.md @@ -0,0 +1,148 @@ + + + +****SWMU arguments (when entering the command runswmu -h):**** + +**mandatory arguments:** + -- UNITS unit amount + --mode MODE mode run | sim | simfast + +**optional arguments for "run" mode:** +*--latitude LATITUDE* +latitude (default 47.687622035085916) + +*--longitude LONGITUDE* +longitude (default 17.744894027593666) + +*--domain DOMAIN* +current domain (default HU00) + +*--near_by_domain NEAR_BY_DOMAIN* +near by domain (default HU00) + + *--x01 GENERATE_X01* + generate x01 (default True) + + *--x01-pause X01_PAUSE* +x01 pause in seconds (default 5sec) + + *--units-wo-x1a UNITS_WO_X1A* +amount of units that will not generate x1a (default 0) + + *--x1a-pause X1A_PAUSE* +x1a pause in seconds (default 10sec) + + *--x1a-mask X1A_MASK* + x1a mask-type of log: + - 01 - without Regain signal flag; + - 17 - with Regain signal flag (default); + + *--x1a-type X1A_TYPE* + x1a type of log (number of positions): + - 0 - (default); + - 1 - 17pos; + - 2 - 33pos; + + *--x1d GENERATE_X1D* + generate x1d (default True) + + *--x1d-pause X1D_PAUSE* +x1d pause in seconds (default 60sec) + + *--x1d-weight_axles X1D_WEIGHT_AXLES* +x1d weight + number of axles: +- 'auto' - generate 2-10 (default); +- '42' - set weight 4, axle 2; +- '76' - set weight 7, axle 6; +- '22' - set weight 2, axle 2; +- .. + +**optional arguments for "sim" and "simfast" mode:** + --log IMPORT_DIR + path to simulated log (obligatory with "sim" mode) + + --simulate_pause SIMULATE_PAUSE + used for mode "simfast" to set delay between each message in seconds (default 2) + +**shared arguments:** + *-h, --help* + show this help message and exit + +*--server-host SERVER_HOST* +server host (default localhost) + +*--server-port SERVER_PORT* +server port (default 31001) + +*--start-id32 START_ID32* +start id32 (default 3567779840) + +*--start-port START_PORT* +start port (default 1024) + +*--bt-spontaneous-timeout BT_SPONTANEOUS_TIMEOUT* +BT spontaneous timeout in seconds (default 20) + +*--sigma SIGMA* +sigma in seconds (default 0.2) + +*--sta SEND_STA* +send sta (default True) + +*--sta-pause STA_PAUSE* +STA pause in seconds (default 30sec) + +****SWMU examples:**** + +Example for 5 Software Mobile Units and server host `localhost`: +```bash +$ runswmu 5 --mode run +``` +```bash +$ runswmu 5 --mode sim --log ./test_log.log +``` +```bash +$ runswmu 5 --mode simfast --log ./test_log.log --simulate_pause 0.25 + ``` +**Other examples**: +```bash +$ runswmu 1 --mode run --server-host localhost --start-id32 3567779841 +``` +```bash +$ runswmu 1 --mode sim --server-host localhost --start-id32 3567779841 --log ./test_log.log +``` +```bash +$ runswmu 1 --mode run --server-host 10.48.172.135 --start-id32 3567779841 --bt-spontaneous-timeout 5 --simulate_pause 0.25 +``` +```bash +$ LOG_LEVEL="INFO" runswmu 5 --mode sim --server-host localhost --start-id32 3567779871 --bt-spontaneous-timeout 5 --simulate_pause 0.25 --log ./test_log.log +``` +```bash +$ LOG_LEVEL="INFO" runswmu 2500 --mode run --server-host 10.48.172.135 --bt-spontaneous-timeout 20 --sigma 3 --sta True --sta-pause 60 --x01-pause 11 --x1d-pause 250 --x1a-pause 18 --x1a-type 1 --domain DE00 --near_by_domain CZ00 --start-id32 3567779841 +``` +```bash +$ runswmu 1 --mode run --server-host 10.48.172.135 --start-id32 3567779841 --bt-spontaneous-timeout 5 --simulate_pause 0.25 +``` +```bash +$ runswmu 50 --mode simfast --server-host localhost --start-id32 3567779841 --log ./test_log.log --simulate_pause 0.25 +``` + +**how to create pod (k8s):** +```bash +$ kubectl [-n namespace] run [name_of_pod] --rm -i --tty --image [name_of_image] -- /bin/bash +``` +```bash +$ kubectl -n uhura-azure-wagexp run swmu --namespace=uhura-azure-wagexp --image=python --requests=cpu=100m,memory=512Mi --limits=cpu=200m,memory=2048Mi --rm -i --tty -- /bin/bash +``` + +```bash +$ kubectl -n uhura-azure-wagexp run swmu --rm -i --tty --image python -- /bin/bash + ``` + +**how to add mulog_file to k8s pod**: +```bash +$ kubectl [-n namespace] cp [path to mulog file] [pod_name]:/ +``` +```bash +$ kubectl -n uhura-azure-wagexp cp /home/directory/test_log.log swmu:/ +``` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c7aba34 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +Flask +# colorlog +crc16 +folium +Werkzeug +pandas +# requests +# our packages +muidconv +directive diff --git a/scripts/create_mulog.py b/scripts/create_mulog.py new file mode 100644 index 0000000..4f5a533 --- /dev/null +++ b/scripts/create_mulog.py @@ -0,0 +1,56 @@ +import logging +import time + +from scripts import utils +from directive.munet.log_record import identify, parse, full_parse + +# from .settings import conf + +LOGGER = logging.LoggerAdapter( + logging.getLogger("swmu"), {"unitid": "unassigned"}) + + +def load_log(import_dir, sim_time_check): + with open(import_dir) as fin: + # take only message even when row is f"{log_address}: {message}" + fin_data = [row.split(":")[-1].strip() for row in fin] + index = 0 + list_ts = [] + list_ts_warning = [] + five_year = time.time() - 157784630 + + for message in fin_data: + message_ts = utils.get_timestamp_of_message( + bytes.fromhex(message)) + if sim_time_check == "max_y" and message_ts is not None: + if message_ts < five_year: + list_ts_warning.append( + (index, message, message_ts)) + continue + message_type = identify(bytes.fromhex(message)) + try: + message_type_parse = parse(bytes.fromhex(message)) + message_type_full_parse = full_parse(bytes.fromhex(message)) + except Exception: + # except Exception as e: + # logging.warning(e) + continue + if message_ts is not None and message_ts <= 423792000: + list_ts_warning.append( + (index, message, message_ts)) + list_ts.append( + (index, message, message_ts, message_type, message_type_parse, + message_type_full_parse, list_ts_warning)) + index += 1 + """ + if list_ts_warning: + LOGGER.warning( + f"timestamp in mulog is suspicious ([row in mulog]" + f", [message], [timestamp]): {list_ts_warning}") + """ + return list_ts + + +def dir_mulog(import_dir, sim_time_check): + mulog_data = load_log(import_dir, sim_time_check) + return mulog_data diff --git a/scripts/utils.py b/scripts/utils.py new file mode 100644 index 0000000..2a12a88 --- /dev/null +++ b/scripts/utils.py @@ -0,0 +1,139 @@ +CHARTOITA2 = { + "A": int("11000", 2), + "B": int("10011", 2), + "C": int("01110", 2), + "D": int("10010", 2), + "E": int("10000", 2), + "F": int("10110", 2), + "G": int("01011", 2), + "H": int("00101", 2), + "I": int("01100", 2), + "J": int("11010", 2), + "K": int("11110", 2), + "L": int("01001", 2), + "M": int("00111", 2), + "N": int("00110", 2), + "O": int("00011", 2), + "P": int("01101", 2), + "Q": int("11101", 2), + "R": int("01010", 2), + "S": int("10100", 2), + "T": int("00001", 2), + "U": int("11100", 2), + "V": int("01111", 2), + "W": int("11001", 2), + "X": int("10111", 2), + "Y": int("10101", 2), + "Z": int("10001", 2), + "": int("00010", 2), + "": int("01000", 2), + "": int("11111", 2), + "": int("11011", 2), + "": int("00100", 2), + "": int("00000", 2), +} + +# message type: offset (bytes) +MESSAGE_TYPE_TIMESTAMP_OFFSET = { + 0x01: 8, + 0x02: 4, + 0x04: 8, + 0x10: 4, + 0x14: 4, + 0x1a: 4, + 0x1d: 4, + 0x23: 4, + 0x0b85: 4, + 0x1c01: 4, + 0x1c02: 4, +} + + +def bytes2uint(input_bytes): + return int.from_bytes(input_bytes, byteorder="big") + + +def bytes2uintle(input_bytes): + return int.from_bytes(input_bytes, byteorder="little") + + +def bytes2hex(input_bytes): + return input_bytes.hex() + + +def bytes2str(input_bytes): + return input_bytes.decode() + + +def parse(input_bytes, item_iter): + item_dict = {} + for item in item_iter: + name, a_slice, function = item + result = input_bytes[a_slice] + if function: + result = function(result) + item_dict[name] = result + return item_dict + + +def mask_flag_dict(flag_bytes, flag_name_mask_iter): + flag_int = int.from_bytes(flag_bytes, byteorder="big") + flag_dict = {} + for flag_name, mask in flag_name_mask_iter: + flag_dict[flag_name] = mask & flag_int + return flag_dict + + +def get_domain(domain_str): + if len(domain_str) == 4: + country_code = domain_str[0:2] + subdomain_code = int(domain_str[2]) + status = int(domain_str[3]) + int(0x04) # 0x04 to activate + domain_int = 0 + domain_int |= CHARTOITA2[country_code[0]] << 11 + domain_int |= CHARTOITA2[country_code[1]] << 6 + domain_int |= subdomain_code << 3 + domain_int |= status + return domain_int.to_bytes(2, byteorder="big") + else: + raise ValueError(f"domain '{domain_str}' 4 characters expected") + + +def circular_increment(value, min_value, max_value): + value += 1 + # value must be between 'min_value' and 'max_value' inclusive + if value > max_value: + value = min_value + return value + + +def get_message_type(message: bytes): + try: + message_type = message[0] + except IndexError as ie: + print(f"IndexError occurs in get_message_type: \n\n{ie}") + return None + if message_type in (0x0b, 0x1c): + return int.from_bytes(message[:2], byteorder="big") + return message_type + + +def get_timestamp_of_message(message: bytes): + message_type = get_message_type(message) + if message_type in MESSAGE_TYPE_TIMESTAMP_OFFSET: + index = MESSAGE_TYPE_TIMESTAMP_OFFSET[message_type] + ts = int.from_bytes(message[index:index + 4], byteorder="big") + return ts + return None + + +def set_timestamp_of_message(message: bytes, ts): + message_type = get_message_type(message) + if message_type in MESSAGE_TYPE_TIMESTAMP_OFFSET: + index = MESSAGE_TYPE_TIMESTAMP_OFFSET[message_type] + message = ( + message[:index] + + int(ts).to_bytes(4, byteorder="big") + + message[index + 4:] + ) + return message diff --git a/static/index.css b/static/index.css new file mode 100644 index 0000000..27ed0fa --- /dev/null +++ b/static/index.css @@ -0,0 +1,399 @@ +/* ** CSS styles ** */ + +/* LOGO_TEXT */ +@import url('https://fonts.googleapis.com/css?family=Holtwood+One+SC'); +.logo{ + font-family: "Holtwood One SC", serif; + /*text-decoration: underline;*/ + text-transform: capitalize; + text-align: center; + font-size: 80px; + color: rgb(75, 86, 87); + background-color: rgba(84, 84, 84, 0); + text-shadow: rgb(245, 230, 230) 2px 2px 2px; +} + + +/* NUMBER_SIZE */ +#number { + width: 5em; +} + +/* just_text */ +.text { +font-family: "Times New Roman", Times, serif; + font-size: 20px; +color: #000; +} + +/* INFO_HELP_text */ +.info_number { +font-family: "Times New Roman", Times, serif; + font-size: 10px; +color: #000; +} + +/* INFO_arguments_text */ +.info_argument { +font-family: "Times New Roman", Times, serif; + font-size: 12px; +color: #000; +} + +/* SWMU_text */ +.swmu { +font-family: "Times New Roman", Times, serif; + font-size: 8px; +color: #000; +} + +/* ign1a_info_text */ +.ign1a_info { +font-family: "Times New Roman", Times, serif;/*font-family: "Audiowide", sans-serif;*/ +font-size: 16px; +} + +/* MODES_text */ +.mode_text { +font-family: "Times New Roman", Times, serif;/*font-family: "Audiowide", sans-serif;*/ +font-size: 18px; +color: #4E4545; +} + +/* mode_text_alert */ +.mode_text_alert { +font-family: "Times New Roman", Times, serif;/*font-family: "Audiowide", sans-serif;*/ +font-size: 12px; +color: #D12A2A; +} + +/* dropbox_text */ +.dropbox_text { +font-family: "Times New Roman", Times, serif;/*font-family: "Audiowide", sans-serif;*/ +font-size: 18px; +color: #4E4545; +/* vertical-align: top;*/ +text-align: left; +} + +/* Parameters_text */ +.parameters_text { +font-family: "Times New Roman", Times, serif;/*font-family: "Audiowide", sans-serif;*/ + font-size: 15px; +color: #4E4545; +} + +/** IMAGE_swmu **/ +.center { + display: block; + margin-left: auto; + margin-right: auto; + width: 50%; +} + +/** DOWN_BUTT **/ +.button_mode { + background-color: #ddd; + border: none; + color: black; + padding: 10px 20px; + text-align: center; + text-decoration: none; + display: inline-block; + margin: 4px 2px; + cursor: pointer; + border-radius: 16px; +} + +/* Place the navbar at the bottom of the page, and make it stick */ +.navbar { + background-color: #333; + overflow: hidden; + position: fixed; + bottom: 0; + width: 100%; +} + +/* Style the links inside the navigation bar */ +.navbar a { + float: left; + display: block; + color: #f2f2f2; + text-align: center; + padding: 14px 16px; + text-decoration: none; + font-size: 17px; +} + +/* Change the color of links on hover */ +.navbar a:hover { + background-color: #ddd; + color: black; +} + +/* Add a color to the active/current link */ +.navbar a.active { + background-color: #04AA6D; + color: white; +} + + +/* RADIO */ +.radio_text { +font-family: "Times New Roman", Times, serif; + font-size: 20px; + color: #4E4545; +} + +#content1, #content2, #content3 { display:none; } + + +#toggle1:checked ~ #content1 +{ + display: block; +} + +#toggle2:checked ~ #content2 +{ + display: block; +} + +#toggle3:checked ~ #content3 +{ + display: block; +} + +.text-center { + text-align: center; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +/* RUN_BUTTON */ +.run_butt { + align-items: center; + background-color: initial; + background-image: linear-gradient(#464d55, #25292e); + border-radius: 8px; + border-width: 0; + box-shadow: 0 10px 20px rgba(0, 0, 0, .1),0 3px 6px rgba(0, 0, 0, .05); + box-sizing: border-box; + color: #fff; + cursor: pointer; + display: inline-flex; + flex-direction: column; + /*font-family: expo-brand-demi,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";*/ + /*font-family: "Audiowide", sans-serif;*/ + font-family: "Times New Roman", Times, serif; + font-size: 24px; + height: 70px; + justify-content: center; + line-height: 1; + margin: 0; + outline: none; + overflow: hidden; + padding: 0 32px; + text-align: center; + text-decoration: none; + transform: translate3d(0, 0, 0); + transition: all 150ms; + vertical-align: baseline; + white-space: nowrap; +} + + + +.run_butt:hover { + box-shadow: rgba(0, 1, 0, .2) 0 2px 8px; + opacity: .85; +} + +.run_butt:active { + outline: 0; +} + +.run_butt:focus { + box-shadow: rgba(0, 0, 0, .5) 0 0 0 3px; +} + +@media (max-width: 420px) { + .run_butt { + height: 48px; + } + +/** SELECTOR_INFO **/ +body { + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto; + height: 100vh; + background-color: #f1f1f1; + } + +input { + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto; + } + +label { + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto; + } + +select { + margin-bottom: 10px; + margin-top: 10px; + } + + + + +} + +.selectt { + /*color: #fff;*/ + padding: 30px; + display: none; + margin-top: 30px; + width: 60%; + /*background: grey*/ + } + + label { + margin-right: 20px; + } + +/** BOX_ITEMS **/ +.clearfix { + content: ""; + clear: both; + display: table; + border-style: groove; + + /*display: block;*/ + /*margin-left: 700px;*/ + margin-left: auto; + margin-right: auto; + width: 800px; + /*margin-right: auto;*/ +} + + +/** HELP **/ +helpswmu { + position: absolute; + right: 0; +} + +/* CLEAR_BUTT */ +.clear_butt { + align-items: center; + background-color: initial; + background-image: linear-gradient(#464d55, #8c2323); + border-radius: 8px; + border-width: 0; + box-shadow: 0 10px 20px rgba(0, 0, 0, .1),0 3px 6px rgba(0, 0, 0, .05); + box-sizing: border-box; + color: #fff; + cursor: pointer; + display: inline-flex; + flex-direction: column; + /*font-family: expo-brand-demi,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";*/ + /*font-family: "Audiowide", sans-serif;*/ + font-family: "Times New Roman", Times, serif; + font-size: 15px; + height: 20px; + justify-content: center; + line-height: 1; + margin: 0; + outline: none; + overflow: hidden; + padding: 0 10px; + text-align: center; + text-decoration: none; + transform: translate3d(0, 0, 0); + transition: all 150ms; + vertical-align: baseline; + white-space: nowrap; +} + +.clear_butt:hover { + box-shadow: rgba(0, 1, 0, .2) 0 2px 8px; + opacity: .85; +} + +.clear_butt:active { + outline: 0; +} + +.clear_butt:focus { + box-shadow: rgba(0, 0, 0, .5) 0 0 0 3px; +} + +@media (max-width: 420px) { + .clear_butt { + height: 48px; + } + +/* file_butt */ +.file_butt { + align-items: center; + background-color: initial; + background-image: linear-gradient(#464d55, #25292e); + border-radius: 8px; + border-width: 0; + box-shadow: 0 10px 20px rgba(0, 0, 0, .1),0 3px 6px rgba(0, 0, 0, .05); + box-sizing: border-box; + color: #fff; + cursor: pointer; + display: inline-flex; + flex-direction: column; + /*font-family: expo-brand-demi,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";*/ + /*font-family: "Audiowide", sans-serif;*/ + font-family: "Times New Roman", Times, serif; + font-size: 24px; + height: 70px; + justify-content: center; + line-height: 1; + margin: 0; + outline: none; + overflow: hidden; + padding: 0 32px; + text-align: center; + text-decoration: none; + transform: translate3d(0, 0, 0); + transition: all 150ms; + vertical-align: baseline; + white-space: nowrap; +} + + + +.file_butt:hover { + box-shadow: rgba(0, 1, 0, .2) 0 2px 8px; + opacity: .85; +} + +.file_butt:active { + outline: 0; +} + +.file_butt:focus { + box-shadow: rgba(0, 0, 0, .5) 0 0 0 3px; +} + +@media (max-width: 420px) { + .file_butt { + height: 48px; + } diff --git a/static/pic/SWMU-logos_transparent.png b/static/pic/SWMU-logos_transparent.png new file mode 100644 index 0000000..3264efb Binary files /dev/null and b/static/pic/SWMU-logos_transparent.png differ diff --git a/static/pic/SWMU-logos_transparent2.png b/static/pic/SWMU-logos_transparent2.png new file mode 100644 index 0000000..1987eea Binary files /dev/null and b/static/pic/SWMU-logos_transparent2.png differ diff --git a/static/pic/SWMU-logos_transparent3.png b/static/pic/SWMU-logos_transparent3.png new file mode 100644 index 0000000..ca8b9b3 Binary files /dev/null and b/static/pic/SWMU-logos_transparent3.png differ diff --git a/static/pic/favicon.ico b/static/pic/favicon.ico new file mode 100644 index 0000000..c3bca6c Binary files /dev/null and b/static/pic/favicon.ico differ diff --git a/templates/helpswmu.html b/templates/helpswmu.html new file mode 100644 index 0000000..93a37c0 --- /dev/null +++ b/templates/helpswmu.html @@ -0,0 +1,143 @@ + + + + + + + + +
+ +
+ + + + + + + + + + +SWMU + + + +
+
+SWMU examples:
+
+Example for 5 Software Mobile Units and server host `localhost`:
+$ runswmu 5 --mode run
+$ runswmu 5 --mode sim --log ./test_log.log
+$ runswmu 5 --mode simfast --log ./test_log.log --simulate_pause 0.25
+
+Other examples:
+$ runswmu 1 --mode run --server-host localhost --start-id32 3567779841
+$ runswmu 1 --mode sim --server-host localhost --start-id32 3567779841 --log ./test_log.log
+$ runswmu 1 --mode run --server-host 10.48.172.135 --start-id32 3567779841 --bt-spontaneous-timeout 5  --simulate_pause 0.25
+$ LOG_LEVEL="INFO" runswmu 5 --mode sim --server-host localhost --start-id32 3567779871 --bt-spontaneous-timeout 5  --simulate_pause 0.25 --log ./test_log.log
+$ LOG_LEVEL="INFO" runswmu 2500 --mode run --server-host 10.48.172.135 --bt-spontaneous-timeout 20 --sigma 3 --sta True --sta-pause 60 --x01-pause 11 --x1d-pause 250 --x1a-pause 18 --x1a-type 1
+        --domain DE00 --near_by_domain CZ00 --start-id32 3567779841
+$ runswmu 1 --mode run --server-host 10.48.172.135 --start-id32 3567779841 --bt-spontaneous-timeout 5  --simulate_pause 0.25
+$ runswmu 50 --mode simfast --server-host localhost --start-id32 3567779841 --log ./test_log.log --simulate_pause 0.25
+
+how to create pod (k8s):
+$ kubectl [-n namespace] run [name_of_pod] --rm -i --tty --image [name_of_image] -- /bin/bash
+$ kubectl -n uhura-azure-wagexp run swmu --namespace=uhura-azure-wagexp --image=principazureacr.azurecr.io/uhura/swmu-0.1.0 --requests=cpu=100m,memory=512Mi --limits=cpu=200m,memory=2048Mi --rm -i --tty -- /bin/bash
+$ kubectl -n uhura-azure-wagexp run swmu --rm -i --tty --image=python -- /bin/bash
+
+how to add mulog_file to k8s pod:
+$ kubectl [-n namespace] cp [path to mulog file] [pod_name]:/
+$ kubectl -n uhura-azure-wagexp cp /home/directory/test_log.log swmu:/data
+
+
+
+
+SWMU arguments (command runswmu -h):
+
+mandatory arguments:
+  UNITS                 unit amount
+  --mode MODE           mode run | sim | simfast
+
+optional arguments for "run" mode:
+  --latitude LATITUDE   latitude (default 47.687622035085916)
+  --longitude LONGITUDE
+                        longitude (default 17.744894027593666)
+  --domain DOMAIN       current domain (default HU00)
+  --near_by_domain NEAR_BY_DOMAIN
+                        near by domain (default HU00)
+  --x01 GENERATE_X01    generate x01 (default True)
+  --x01-pause X01_PAUSE
+                        x01 pause in seconds (default 5s)
+  --units-wo-x1a UNITS_WO_X1A
+                        amount of units that will not generate x1a (default 0)
+  --x1a-pause X1A_PAUSE
+                        x1a pause in seconds (default 10s)
+  --x1a-mask X1A_MASK   x1a mask-type of log: 01 - without Regain signal flag; 17 - with Regain signal flag (default)
+  --x1a-type X1A_TYPE   x1a type of log (number of positions): 0 - (default); 1 - 17pos; 2 - 33pos
+  --x1d GENERATE_X1D    generate x1d (default True)
+  --x1d-pause X1D_PAUSE
+                        x1d pause in seconds (default 60sec)
+  --x1d-weight_axles X1D_WEIGHT_AXLES
+                        x1d weight + number of axles: 'auto' - generate 2-10 (default); '42' - set weight 4, axle 2; '76' - set weight 7, axle 6;
+
+optional arguments for "sim" or "simfast" mode:
+  --log IMPORT_DIR      path to simulated log (obligatory with "sim" and "simfast" mode)
+  --simulate_pause SIMULATE_PAUSE
+                        used for mode "simfast" to set delay between each message in seconds (default 2s)
+  --sim_time_check SIM_TIME_CHECK
+                        used for mode 'sim' to check timestamp:
+                        1) if 'no' is set, there is no changes in timestamp (default)
+                        2) if 'max' is set, the the wait between two messages cannot be greater than 60s
+                        3) if 'max_y' is set, the messages older then 5 years are ignored
+  --sim_stop SIM_STOP   turn off/on auto-loop-close for sim/simfast mode (default True)
+
+
+shared arguments:
+  -h, --help            show this help message and exit
+  --server-host SERVER_HOST
+                        server host (default localhost)
+  --server-port SERVER_PORT
+                        server port (default 31001)
+  --start-id32 START_ID32
+                        start id32 (default 3567779840)
+  --start-port START_PORT
+                        start port (default 1024)
+  --bt-spontaneous-timeout BT_SPONTANEOUS_TIMEOUT
+                        BT spontaneous timeout in seconds (default 20)
+  --sigma SIGMA         sigma in seconds (default 0.2)
+  --sta SEND_STA        send sta (default True)
+  --sta-pause STA_PAUSE
+                        STA pause in seconds (default 30sec)
+
+
+    
+
+ +
+ +
+ + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..575c3c9 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,24 @@ + + + + + The jQuery Example + +

jQuery-AJAX in FLASK. Execute function on button click

+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/index_v2.html b/templates/index_v2.html new file mode 100644 index 0000000..8ae5239 --- /dev/null +++ b/templates/index_v2.html @@ -0,0 +1,636 @@ + + + + + + + + +
+ + TEST +
+ + + + + + + + + + +SWMU + + + +
+ +
+ +
+ +
+
+ +
+ + +
+ + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + + + + +
+ +
 
+ +
+ +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ + +
+ + +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + +
+ +
+
+ +
+ +
+ + +
+ + +
+ +
+
+ +
+ + + + +
+ +
+ + + + +
+ +
+
+ + +
+ + +
+ +
+
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ +
+ + +
+ + + +
+ + +
+ + + + + + + + + +
+ {% if clear == False %} + {% if questions %} +
+ {% for question in questions %} + {% if "None" == question.mode %} +
+ LOG_LEVEL="{{question.loglevel}}" runswmu {{question.number_swmu}} --mode run --start-id32 {{question.id32}} --server-host {{question.server_host}} --server-port {{question.server_port}} --start-port {{question.start_port}} --bt-spontaneous-timeout {{question.bt_spontaneous_timeout}} --sigma {{question.sigma}} --sta {{question.sta}} --sta-pause {{question.sta_pause}} --ft_delay {{question.ft_delay}} --ft_mode {{question.ft_mode}}
+
+ + {% elif "run" == question.mode %} +
+ LOG_LEVEL="{{question.loglevel}}" + runswmu {{question.number_swmu}} + --mode {{question.mode}} + --start-id32 {{question.id32}} + --server-host {{question.server_host}} + --server-port {{question.server_port}} + --start-port {{question.start_port}} + --bt-spontaneous-timeout {{question.bt_spontaneous_timeout}} + --sigma {{question.sigma}} + --sta {{question.sta}} + --sta-pause {{question.sta_pause}} + --ft_delay {{question.ft_delay}} + --ft_mode {{question.ft_mode}} + --latitude {{question.latitude}} + --longitude {{question.longitude}} + --domain {{question.domain}} + --near_by_domain {{question.near_by_domain}} + --x01 {{question.x01}} + --x01-pause {{question.x01_pause}} + --units-wo-x1a {{question.units_wo_x1a}} + --x1a-pause {{question.x1a_pause}} + --x1a-mask {{question.x1a_mask}} + --x1a-type {{question.x1a_type}} + --x1d {{question.x1d}} + --x1d-pause {{question.x1d_pause}} + --x1d-weight_axles {{question.x1d_weight_axles}}
+
+ + {% elif "sim" == question.mode %} +
+ LOG_LEVEL="{{question.loglevel}}" + runswmu {{question.number_swmu}} + --mode {{question.mode}} + --start-id32 {{question.id32}} + --server-host {{question.server_host}} + --server-port {{question.server_port}} + --start-port {{question.start_port}} + --bt-spontaneous-timeout {{question.bt_spontaneous_timeout}} + --sigma {{question.sigma}} + --sta {{question.sta}} + --sta-pause {{question.sta_pause}} + --ft_delay {{question.ft_delay}} + --ft_mode {{question.ft_mode}} + --log {{question.log}} + --sim_time_check {{question.sim_time_check}} + --sim_stop {{question.sim_stop}}
+
+ + {% elif "simfast" == question.mode %} +
+ LOG_LEVEL="{{question.loglevel}}" + runswmu {{question.number_swmu}} + --mode {{question.mode}} + --start-id32 {{question.id32}} + --server-host {{question.server_host}} + --server-port {{question.server_port}} + --start-port {{question.start_port}} + --bt-spontaneous-timeout {{question.bt_spontaneous_timeout}} + --sigma {{question.sigma}} + --sta {{question.sta}} + --sta-pause {{question.sta_pause}} + --ft_delay {{question.ft_delay}} + --ft_mode {{question.ft_mode}} + --log {{question.log}} + --sim_time_check {{question.sim_time_check}} + --sim_stop {{question.sim_stop}} + --simulate_pause {{question.simulate_pause}}
+
+ + {% endif %} + {% endfor %} +
+ {% endif %} + {% else %} +
+ + {% endif %} + +
 
+
 
+
 
+
+ +
+ +
+ + + \ No newline at end of file diff --git a/templates/info.html b/templates/info.html new file mode 100644 index 0000000..e381b35 --- /dev/null +++ b/templates/info.html @@ -0,0 +1,51 @@ + + + + + + + + +
+ +
+ + + + + + + + + + +SWMU + + + +
+ +
+ + + \ No newline at end of file diff --git a/templates/mulog_read.html b/templates/mulog_read.html new file mode 100644 index 0000000..232848e --- /dev/null +++ b/templates/mulog_read.html @@ -0,0 +1,202 @@ + + + + + + + + +
+ +
+ + + + + + + + + + + +SWMU + + +
+
supports only .log format with max file size {{ max_size }}mb
+
+
+
+
+ + + + + + + + +
+
+ {% if files %} + {% for file in files %} + +
+ Download log + Download position file + +
name: {{files}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
x01_log_book_record: {{mulog[0]}} +  info + x04_driver_login: {{mulog[1]}} +  info +
x05_driver_logout: {{mulog[2]}} +  info + x08x09_log_record: {{mulog[3]}} +  info +
x08x09_log_record: {{mulog[4]}} +  info + x13_driving_style: {{mulog[5]}} +  info +
x1400_accelerometer_event: {{mulog[6]}} +  info + x25_perfect_drive: {{mulog[7]}} +  info +
x26_long_mext: {{mulog[8]}} +  info + x0b_log_record: {{mulog[9]}} +  info +  info + +
x0d_log_record: {{mulog[10]}} +  info + x1a_fastlog: {{mulog[11]}} +  info +
x1c_log_record: {{mulog[12]}} +  info + x1d_domain_vehicle_parameters: {{mulog[13]}} +  info +
0x0e_record: {{mulog[15]}} +  info + other_type: {{mulog[16]}}
0x10_record: {{mulog[14]}} +  info +
+ + + + + +
number of timestamps: {{ts_c}}number of positions: {{pos_c}}
+ + {% if pos_c > max_pos %} + + + + +
recommended amount position for rendering is {{max_pos}}, otherwise, it may cause delay or instability
+ {% endif %} + + {% if warn %} +
+ timestamp in mulog is suspicious ([row in mulog], [message], [timestamp]): {list_ts_warning} {{warn}} +
+ {% endif %} + {% if text %} + {{text}} + {% endif %} +
+ {% endfor %} + {% endif %} +
+ +
+
+ + {% if files %} + {% if text %} + {% else %} +
+ +
+ {% endif %} + {% endif %} +
+ +
+
+
 
+
 
+
 
+
+ +
+ +
+ + + \ No newline at end of file diff --git a/templates/test.html b/templates/test.html new file mode 100644 index 0000000..95a3ce0 --- /dev/null +++ b/templates/test.html @@ -0,0 +1,17 @@ + + + + File Upload + + +

File Upload

+
+

+

+
+
+ {% for file in files %} + + {% endfor %} + + \ No newline at end of file diff --git a/uploads/.a b/uploads/.a new file mode 100644 index 0000000..e69de29