- Improve speed testing with using 2 threads, one to saturate connection with speedtest.net and another to get rates from router's API
- Logging fix dual entriesmaster
parent
e3b07d0947
commit
5191643ac6
|
|
@ -136,3 +136,4 @@ test.py
|
|||
test.png
|
||||
data/database.db-shm
|
||||
data/database.db-wal
|
||||
test2.py
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
'''
|
||||
Main application file
|
||||
'''
|
||||
|
||||
import eventlet
|
||||
eventlet.monkey_patch()
|
||||
|
||||
from flask import Flask, jsonify
|
||||
from flask_socketio import SocketIO
|
||||
|
||||
from datetime import datetime
|
||||
import dbo
|
||||
|
||||
# region Logger
|
||||
import logging
|
||||
from debug import setup_logging
|
||||
|
||||
log = logger = logging.getLogger("default")
|
||||
setup_logging()
|
||||
# endregion
|
||||
|
||||
from configuration import read_config
|
||||
from peewee import fn
|
||||
|
||||
config = read_config()
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['SECRET_KEY'] = 'BLAAAA_GeneerateMeDynamicallyForBetterSecurity'
|
||||
|
||||
socketio = SocketIO(app, async_mode='eventlet')
|
||||
|
||||
|
||||
# app.jinja_env.filters['html_line_breaks'] = jinja_filters.html_line_breaks
|
||||
# app.jinja_env.filters['zfill'] = jinja_filters.zfill
|
||||
|
||||
@app.context_processor
|
||||
def inject_global_variables():
|
||||
return dict(
|
||||
config=config,
|
||||
now=datetime.utcnow(),
|
||||
Accounting=dbo.Accounting,
|
||||
MonthlyArchive=dbo.MonthlyArchive,
|
||||
fn=fn
|
||||
)
|
||||
|
||||
|
||||
def add_background_task(task, interval):
|
||||
def tsk():
|
||||
while True:
|
||||
try:
|
||||
log.debug(f"Running background task {task.__name__}...")
|
||||
task()
|
||||
log.debug(f"Completed background task {task.__name__}!")
|
||||
except Exception as e:
|
||||
log.error(f"Can't run background task '{task.__name__}': {e}", exc_info=True)
|
||||
socketio.sleep(interval)
|
||||
|
||||
socketio.start_background_task(tsk)
|
||||
|
||||
@app.route("/api/")
|
||||
def api_index():
|
||||
return jsonify(
|
||||
{""}
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
config = read_config()
|
||||
|
||||
try:
|
||||
if config['host'] == "0.0.0.0":
|
||||
host = 'localhost'
|
||||
else:
|
||||
host = config['host']
|
||||
log.info(f"Running at http://{host}:{config['port']}")
|
||||
socketio.run(app, debug=False, host=config['host'], port=config['port'])
|
||||
except:
|
||||
print("Unable to start", exc_info=True)
|
||||
|
||||
|
||||
|
||||
|
|
@ -13,6 +13,9 @@ ros_minimum_speed: 300000
|
|||
# starts to show high CPU usage at close to 20mbit.
|
||||
# Not implemented yet
|
||||
ros_maximum_speed: 15000000 # 15 mbit
|
||||
ros_wan_interface: lte1
|
||||
api_host: 0.0.0.0
|
||||
api_port: 1357
|
||||
|
||||
|
||||
# Conversion rate 1 mbit : 1000000 bits
|
||||
|
|
@ -23,9 +23,9 @@ handlers:
|
|||
|
||||
root:
|
||||
level: ERROR
|
||||
handlers: [debug_file_handler]
|
||||
handlers: [console]
|
||||
|
||||
loggers:
|
||||
"default":
|
||||
level: DEBUG
|
||||
handlers: [debug_file_handler, console]
|
||||
handlers: [debug_file_handler]
|
||||
|
|
|
|||
4
paths.py
4
paths.py
|
|
@ -9,3 +9,7 @@ import os
|
|||
APP_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
CONFIG_DIR = os.path.join(APP_DIR, "config")
|
||||
DATA_DIR = os.path.join(APP_DIR, "data")
|
||||
|
||||
|
||||
cache1 = os.path.join(APP_DIR, 'cache1.yaml')
|
||||
cache2 = os.path.join(APP_DIR, 'cache2.yaml')
|
||||
|
|
|
|||
110
speedtester.py
110
speedtester.py
|
|
@ -6,7 +6,9 @@ from debug import setup_logging, catch_errors
|
|||
log = logger = logging.getLogger("default")
|
||||
setup_logging()
|
||||
# endregion
|
||||
|
||||
from statistics import median
|
||||
from threading import Thread
|
||||
import speedtest
|
||||
from dbo import Entry
|
||||
import routeros_api
|
||||
|
||||
|
|
@ -16,6 +18,10 @@ secrets = read_config('secrets')
|
|||
import time
|
||||
|
||||
|
||||
def mbits(bits):
|
||||
return round(bits / 1000000, 2)
|
||||
|
||||
|
||||
@catch_errors
|
||||
def gather_data():
|
||||
log.debug("Gathering data...")
|
||||
|
|
@ -90,7 +96,7 @@ def ros_dynamic_speed(upload, download):
|
|||
:param upload: Upload speed from speedtest
|
||||
:param download: Download speed from speedtest
|
||||
'''
|
||||
|
||||
log.debug(f"Set Dynamic Speed to: DOWN {mbits(download)} mbps; UP {mbits(upload)} mbps")
|
||||
connection = routeros_api.RouterOsApiPool(config['ros_ip'], username=secrets["ros_login"],
|
||||
password=secrets["ros_password"], plaintext_login=True)
|
||||
api = connection.get_api()
|
||||
|
|
@ -100,7 +106,7 @@ def ros_dynamic_speed(upload, download):
|
|||
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)}")
|
||||
f"Adjust Queue {queue['name']}: 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
|
||||
|
|
@ -111,35 +117,82 @@ def ros_dynamic_speed(upload, download):
|
|||
connection.disconnect()
|
||||
|
||||
|
||||
def speedtest():
|
||||
import speedtest
|
||||
|
||||
servers = []
|
||||
wan_upload = None
|
||||
wan_download = None
|
||||
results_dict = None
|
||||
test_started = False
|
||||
downloading = True # True for download, False for upload
|
||||
threads = None
|
||||
servers = []
|
||||
|
||||
|
||||
def threaded_speedtest():
|
||||
global test_started
|
||||
global downloading
|
||||
|
||||
for i in range(0, 3):
|
||||
try:
|
||||
log.debug("Initializing speedtest...")
|
||||
s = speedtest.Speedtest()
|
||||
|
||||
log.debug(f"Running test...")
|
||||
s.get_servers(servers)
|
||||
s.get_best_server()
|
||||
print(f"Running test...")
|
||||
test_started = True
|
||||
downloading = True
|
||||
s.download(threads=threads)
|
||||
downloading = False
|
||||
s.upload(threads=threads, pre_allocate=False)
|
||||
|
||||
global results_dict
|
||||
results_dict = s.results.dict()
|
||||
print(
|
||||
f"Speedtest.net result: DOWN {mbits(results_dict['download'])} mbps; UP {mbits(results_dict['upload'])} mbps;")
|
||||
return results_dict
|
||||
|
||||
if results_dict['download'] >= config['ros_minimum_speed']:
|
||||
download = round(results_dict['download'] / 1000000, 2)
|
||||
upload = round(results_dict['upload'] / 1000000, 2)
|
||||
break
|
||||
time.sleep(10)
|
||||
except:
|
||||
log.error(f"Test failed, try {i + 1}/3", exc_info=True)
|
||||
|
||||
log.debug(f"{download}mbps, {upload}mbps")
|
||||
return download, upload, results_dict
|
||||
def threaded_wan_speed():
|
||||
global test_started
|
||||
global results_dict
|
||||
global downloading
|
||||
print("Waiting for test to start...")
|
||||
while not test_started:
|
||||
time.sleep(1)
|
||||
print("Allow warm-up...")
|
||||
time.sleep(2)
|
||||
uploads = []
|
||||
downloads = []
|
||||
print("Monitoring...")
|
||||
while not results_dict:
|
||||
connection = routeros_api.RouterOsApiPool(config['ros_ip'], username=secrets["ros_login"],
|
||||
password=secrets["ros_password"], plaintext_login=True)
|
||||
api = connection.get_api()
|
||||
|
||||
traffic = api.get_resource('/').call('interface/monitor-traffic',
|
||||
{'interface': config['ros_wan_interface'], 'once': ' '})[0]
|
||||
|
||||
traffic['rx-bits-per-second'] = int(traffic['rx-bits-per-second'])
|
||||
traffic['tx-bits-per-second'] = int(traffic['tx-bits-per-second'])
|
||||
|
||||
if downloading:
|
||||
downloads.append(traffic['rx-bits-per-second'])
|
||||
print(f"DL: {mbits(traffic['rx-bits-per-second'])} mbps;")
|
||||
else:
|
||||
uploads.append(traffic['tx-bits-per-second'])
|
||||
print(f"UP: {mbits(traffic['tx-bits-per-second'])} mbps;")
|
||||
|
||||
time.sleep(1)
|
||||
global wan_download
|
||||
global wan_upload
|
||||
wan_download = median(downloads)
|
||||
wan_upload = median(uploads)
|
||||
print(f"Monitor result: {mbits(wan_download)} mbps; {mbits(wan_upload)} mbps;")
|
||||
|
||||
|
||||
def test_speed():
|
||||
sws = Thread(target=threaded_wan_speed)
|
||||
st = Thread(target=threaded_speedtest)
|
||||
st.start()
|
||||
sws.start()
|
||||
st.join()
|
||||
sws.join()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
'''
|
||||
|
|
@ -157,21 +210,18 @@ if __name__ == "__main__":
|
|||
ros_fastrack_enable(True)
|
||||
time.sleep(5)
|
||||
|
||||
download, upload, results_dict = speedtest()
|
||||
test_speed()
|
||||
|
||||
entry = Entry()
|
||||
entry.upload = upload
|
||||
entry.download = download
|
||||
entry.upload = mbits(wan_upload)
|
||||
entry.download = mbits(wan_download)
|
||||
entry.save()
|
||||
|
||||
ros_upload = results_dict['upload']
|
||||
ros_download = results_dict['download']
|
||||
|
||||
if ros_download < config['ros_minimum_speed']:
|
||||
ros_download = config['ros_minimum_speed']
|
||||
if wan_download < config['ros_minimum_speed']:
|
||||
wan_download = config['ros_minimum_speed']
|
||||
|
||||
if config["ros_dynamic_speed"]:
|
||||
ros_dynamic_speed(results_dict['upload'], results_dict['download'])
|
||||
ros_dynamic_speed(wan_upload, wan_download)
|
||||
ros_fastrack_enable(False)
|
||||
|
||||
dates, downloads, uploads = gather_data()
|
||||
|
|
|
|||
Loading…
Reference in New Issue