Skip to content

Instantly share code, notes, and snippets.

@terabyte
Created May 8, 2020 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save terabyte/966385a7093f3350b34f6fda8419386a to your computer and use it in GitHub Desktop.
Save terabyte/966385a7093f3350b34f6fda8419386a to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import io
import json
import random
import sh
import time
import smtplib, ssl
# these are servers that are both close by and in my testing were able to
# produce gigabit readings.
servers = [
11208,
20875,
5024,
];
# how many servers to use from our list at any one invocation
test_count = 2
# in case wifi gets turned on, ensure we go over gigabit ethernet and error out
# if that doesn't work
interface = "eno1"
# append our log entries here
log_file = '/path/to/speedtest.log'
# used in report output
hostname = sh.hostname('-f')
# minimum expected results, in mbit
min_download = 650.0
min_upload = 25.0
email_server = "smtp.gmail.com"
email_port = 465
email_login = "your.email@gmail.com"
email_password = "your-password-like-a-newb"
destination_emails = [ 'whereitsgoing@example.com' ]
def bytes_to_mbit(b):
return b * 1.0 / 1048576 * 8
def results_to_results_i_care_about(result):
ret = dict()
ret['z_download_bandwidth'] = result['download']['bandwidth']
ret['z_upload_bandwidth'] = result['upload']['bandwidth']
ret['2_download_mbit'] = bytes_to_mbit(ret['z_download_bandwidth'])
ret['3_upload_mbit'] = bytes_to_mbit(ret['z_upload_bandwidth'])
secs = time.time()
lt = time.localtime(secs)
ret['1_date'] = time.strftime("%Y%m%d %H:%M:%S", lt)
ret['z_unix_time'] = secs
ret['z_server_id'] = result["server"]["id"]
ret['z_server_name'] = result["server"]["name"]
ret['z_server_location'] = result["server"]["location"]
return ret
results = []
results_out_of_range = False
servers_to_use = random.sample(servers, test_count)
for server in servers_to_use:
buf = io.StringIO()
sh.speedtest('--server-id=%d' % server, '--format=json', '--interface=%s' % interface, _out=buf)
result = json.loads(buf.getvalue())
#print(json.dumps(results_to_results_i_care_about(result), sort_keys=True, indent=4))
formatted_result = results_to_results_i_care_about(result)
# write data to our log
with open(log_file, 'a+') as f:
f.write(json.dumps(formatted_result))
# save result for email
results.append(formatted_result)
# note if the result was out of range
if formatted_result['2_download_mbit'] < min_download:
results_out_of_range = True
if formatted_result['3_upload_mbit'] < min_upload:
results_out_of_range = True
# only send email if results out of range
if not results_out_of_range:
sys.exit(0)
total_d = 0
total_u = 0
for record in results:
total_d = total_d + record["z_download_bandwidth"]
total_u = total_u + record["z_upload_bandwidth"]
count = len(results)
avg_download = "%.2f" % bytes_to_mbit(total_d * 1.0 / count)
avg_upload = "%.2f" % bytes_to_mbit(total_u * 1.0 / count)
msg = f"""\
Subject: Speed Test Bandwidth Report for {hostname}
The average download speed was: {avg_download} mbit
The average upload speed was: {avg_upload} mbit
The raw records:
"""
for record in results:
msg = msg + json.dumps(record, sort_keys=True, indent=4) + "\n"
# https://realpython.com/python-send-email/
with smtplib.SMTP_SSL(email_server, email_port, context=ssl.create_default_context()) as server:
server.login(email_login, email_password)
for dest in destination_emails:
server.sendmail(email_login, destination_emails, msg)
@terabyte
Copy link
Author

terabyte commented May 8, 2020

This requires the official speedtest client, available here: https://www.speedtest.net/apps/cli
Using the open source one (in debian, speedtest-cli package) cannot measure more than 100mbit down in my experience, due to implementation problems.

@terabyte
Copy link
Author

terabyte commented May 8, 2020

To get a list of nearby servers to fill in the server IDs field, run speedtest -L

@terabyte
Copy link
Author

terabyte commented May 8, 2020

Finally, this only works with a gmail account you have "insecure applications" enabled on. Not sure if it works with an application password (let me know!).

@terabyte
Copy link
Author

terabyte commented May 8, 2020

make a burner gmail account to use if needed.

@terabyte
Copy link
Author

terabyte commented May 8, 2020

ah, yes, dependencies:

$ virtualenv .venv
$ source .venv/bin/activate
$ pip install sh
$ ./venv/bin/python /path/to/this/script.py

Tested with python 3.6

@terabyte
Copy link
Author

terabyte commented May 8, 2020

if you want to look at the log without your eyes bleeding, I recommend:

$ apt install jq
$ cat ~/speedtest.log | jq -c '[.["1_date"],.["2_download_mbit"], .["3_upload_mbit"]]'
["20200508 00:09:42",806.605842590332,30.75140380859375]
["20200508 00:11:24",828.466194152832,34.02489471435547]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment