Add dynamic speed test and queue adjustment

master
Nixellion 2020-06-24 02:46:10 +03:00
parent 692b1f9cf7
commit 84cf9ca13c
7 changed files with 108 additions and 49 deletions

3
.gitignore vendored
View File

@ -131,3 +131,6 @@ dmypy.json
.idea/ .idea/
data/database.db data/database.db
secrets.yaml
test.py
test.png

View File

@ -1,3 +1,9 @@
database_migrate: False database_migrate: False
output_image_path: /var/www/downloads/speedgraph.png output_image_path: speedgraph.png
output_txt_path: /var/www/downloads/speeds.txt output_txt_path: speeds.txt
ros_dynamic_speed: True
ros_ip: 192.168.88.1
ros_queues:
- WAN
ros_du_invert: False
ros_fasttrack_comment: "defconf: fasttrack"

View File

@ -40,18 +40,6 @@ def setup_logging(
logging.basicConfig(level=default_level) logging.basicConfig(level=default_level)
def catch_errors_json(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e), "traceback": traceback.format_exc()})
return wrapped
loggers = {} loggers = {}
@ -70,7 +58,7 @@ def get_logger(name):
log = logger = get_logger("default") log = logger = get_logger("default")
def catch_errors_json(f): def catch_errors(f):
@functools.wraps(f) @functools.wraps(f)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
try: try:
@ -78,18 +66,6 @@ def catch_errors_json(f):
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
log.error(traceback.format_exc()) log.error(traceback.format_exc())
return jsonify({"error": str(e), "traceback": traceback.format_exc()}) return traceback.format_exc()
return wrapped return wrapped
def catch_errors_html(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
traceback.print_exc()
log.error(traceback.format_exc())
return render_template("error.html", error=str(e), error_trace=traceback.format_exc())
return wrapped

View File

@ -1,4 +1,5 @@
peewee peewee
speedtest-cli speedtest-cli
numpy numpy
matplotlib matplotlib
RouterOS-api

BIN
speedgraph.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

4
speeds.txt Normal file
View File

@ -0,0 +1,4 @@
Date: Down; Up;
2020-06-24 02:37:11.363969: 6.29 Mbps; 4.16 Mbps
2020-06-24 02:38:12.903694: 5.52 Mbps; 3.8 Mbps
2020-06-24 02:39:31.212599: 12.07 Mbps; 5.08 Mbps

View File

@ -1,15 +1,22 @@
from configuration import read_config from configuration import read_config
# region Logger # region Logger
import logging import logging
from debug import setup_logging from debug import setup_logging, catch_errors
log = logger = logging.getLogger("default") log = logger = logging.getLogger("default")
setup_logging() setup_logging()
# endregion # endregion
from dbo import Entry from dbo import Entry
import routeros_api
config = read_config()
secrets = read_config('secrets')
import time
@catch_errors
def gather_data(): def gather_data():
log.debug("Gathering data...") log.debug("Gathering data...")
downloads = [] downloads = []
@ -22,18 +29,22 @@ def gather_data():
return dates, downloads, uploads return dates, downloads, uploads
@catch_errors
def generate_plot_image(dates, downloads, uploads): def generate_plot_image(dates, downloads, uploads):
log.debug("Genering image output...") log.debug("Genering image output...")
import matplotlib import matplotlib
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
dates = matplotlib.dates.date2num(dates) dates = matplotlib.dates.date2num(dates)
fig = plt.figure(figsize=(12,3)) fig = plt.figure(figsize=(12, 3))
plt.plot_date(dates, downloads, fmt="b-") plt.plot_date(dates, downloads, fmt="b-")
plt.ylabel('Download Speed Mbps') plt.ylabel('Download Speed Mbps')
plt.tight_layout() plt.tight_layout()
plt.savefig(read_config()['output_image_path']) plt.savefig(read_config()['output_image_path'])
@catch_errors
def generate_txt_output(dates, downloads, uploads): def generate_txt_output(dates, downloads, uploads):
log.debug("Genering txt output...") log.debug("Genering txt output...")
txt = "Date: Down; Up;\n" txt = "Date: Down; Up;\n"
@ -45,6 +56,61 @@ def generate_txt_output(dates, downloads, uploads):
with open(read_config()['output_txt_path'], "w+") as f: with open(read_config()['output_txt_path'], "w+") as f:
f.write(txt) f.write(txt)
@catch_errors
def ros_fastrack_enable(enable):
'''
Enable or disable fasttrack
:param enable: True to enable, False to disable
'''
if enable:
disabled = 'false'
else:
disabled = 'true'
log.info(f"Changing fasttrack disabled to {disabled}")
connection = routeros_api.RouterOsApiPool(config['ros_ip'], username=secrets["ros_login"],
password=secrets["ros_password"], plaintext_login=True)
api = connection.get_api()
filter = api.get_resource('/ip/firewall/filter')
for i in filter.get():
if config['ros_fasttrack_comment'] in i['comment']:
filter.set(id=i['id'], disabled=disabled)
connection.disconnect()
@catch_errors
def ros_dynamic_speed(upload, download):
'''
Adjust router os queue speed.
:param upload: Upload speed from speedtest
:param download: Download speed from speedtest
'''
connection = routeros_api.RouterOsApiPool(config['ros_ip'], username=secrets["ros_login"],
password=secrets["ros_password"], plaintext_login=True)
api = connection.get_api()
list_queues = api.get_resource('/queue/simple')
for queue in list_queues.get():
if queue['name'] in config['ros_queues']:
log.debug(
f"Adjust Queue {queue['name']}: limit_at {int(upload) - int(upload / 10)}/{int(download) - int(download / 10)}; max_limit {int(upload)}/{int(download)}")
if config["ros_du_invert"] == True:
# Inverting upload and download values, because master queue is most likely applied to the bridge
list_queues.set(id=queue['id'], max_limit=f"{int(download)}/{int(upload)}")
else:
# Not inverting, use this in case master queue is applied to something like LTE interface
list_queues.set(id=queue['id'], max_limit=f"{int(upload)}/{int(download)}")
connection.disconnect()
if __name__ == "__main__": if __name__ == "__main__":
''' '''
This script will run a few speed tests, calculate average upload and download speeds and record them into database. This script will run a few speed tests, calculate average upload and download speeds and record them into database.
@ -55,18 +121,22 @@ if __name__ == "__main__":
# import sys # import sys
# sys.exit() # sys.exit()
from random import uniform from random import uniform
try: try:
if config["ros_dynamic_speed"]:
ros_fastrack_enable(True)
time.sleep(5)
import speedtest import speedtest
servers = [] servers = []
threads = None threads = None
for i in range (0, 3): for i in range(0, 3):
try: try:
log.debug("Initializing speedtest...") log.debug("Initializing speedtest...")
s = speedtest.Speedtest() s = speedtest.Speedtest()
log.debug(f"Running test...") log.debug(f"Running test...")
s.get_servers(servers) s.get_servers(servers)
s.get_best_server() s.get_best_server()
@ -74,13 +144,13 @@ if __name__ == "__main__":
s.upload(threads=threads, pre_allocate=False) s.upload(threads=threads, pre_allocate=False)
results_dict = s.results.dict() results_dict = s.results.dict()
download = round(results_dict['download']/1000000, 2) download = round(results_dict['download'] / 1000000, 2)
upload = round(results_dict['upload']/1000000, 2) upload = round(results_dict['upload'] / 1000000, 2)
# download = uniform(0,2) # download = uniform(0,2)
# upload = uniform(0,2) # upload = uniform(0,2)
break break
except: except:
log.error(f"Test failed, try {i+1}/3", exc_info=True) log.error(f"Test failed, try {i + 1}/3", exc_info=True)
log.debug(f"{download}mbps, {upload}mbps") log.debug(f"{download}mbps, {upload}mbps")
@ -88,22 +158,21 @@ if __name__ == "__main__":
entry.upload = upload entry.upload = upload
entry.download = download entry.download = download
entry.save() entry.save()
except:
log.error("Data record error.", exc_info=True)
try: if config["ros_dynamic_speed"]:
ros_dynamic_speed(results_dict['upload'], results_dict['download'])
ros_fastrack_enable(False)
dates, downloads, uploads = gather_data() dates, downloads, uploads = gather_data()
try: generate_txt_output(dates, downloads, uploads)
generate_txt_output(dates, downloads, uploads)
except: generate_plot_image(dates, downloads, uploads)
log.error("Unable to save text file.", exc_info=True)
try:
generate_plot_image(dates, downloads, uploads)
except:
log.error("Unable to save plot file.", exc_info=True)
except: except:
log.error("Error plotting.", exc_info=True) log.error("Error!", exc_info=True)
if config["ros_dynamic_speed"]:
ros_fastrack_enable(False)