Ping test can now use timing from Performance API; New examples; Minor changes

This commit is contained in:
dosse91 2017-10-30 12:35:49 +01:00
parent 57463bd314
commit 046137cf6c
18 changed files with 1391 additions and 803 deletions

138
doc.md
View file

@ -1,7 +1,7 @@
# HTML5 Speedtest
> by Federico Dossena
> Version 4.4, October 14 2017
> Version 4.5, November 1 2017
> [https://github.com/adolfintel/speedtest/](https://github.com/adolfintel/speedtest/)
@ -41,14 +41,47 @@ Later we'll see how to use the test without PHP, and how to configure the teleme
__Important:__ keep all the files together; all paths are relative to the js file
## Basic usage
You can start using this speedtest on your site without any special knowledge.
Start by copying one of the included examples. Here's a description for each of them:
* `example-basic.html`: This example shows the most basic configuration possible. Everything runs with the default settings, in a very simple page where the output is shown
* `example-pretty.html`: This is a more sophisticated example, with a nicer layout and a start/stop button. __This is the best starting point for most users__
* `example-progressBar.html`: A modified version of `example-pretty.html` with a progress indicator
* `example-customSettings.html`: A modified version of `example-pretty.html` showing how the test can be started with custom parameters
* `example-customSettings2.html`: A modified version of `example-pretty.html` showing how to make a custom test with only download and upload
* `example-gauges.html`: The most sophisticated example, with the same functions as `example-pretty.html` but also gauges and progress indicators for each test. This is the nicest example included, and also a good starting point, but drawing the gauges may slow down the test on slow devices like a Raspberry Pi
* `example-chart.html`: The old example5.html, showing how to use the test with the Chart.js library
* `example-telemetry.html`: A modified version of `example-pretty.html` with basic telemetry turned on. See the section on Telemetry for details
## Usage
You can modify one of the examples or start from scratch. If you are just editing one of the example, skip to the "test parameters" section.
### Customizing your example
The included examples are good starting places if you want to have a simple speedtest on your site.
Once you've tested everything and you're sure that everything works, edit it and add some custom stuff like your logo or new colors.
If you want to change the test parameters, for instance to make the download test shorter, you can do so in every example:
Look for the line that contains `postMessage('start `
This is where custom parameters can be passed to the test as a JSON string. You can write the string manually or use ``JSON.stringify`` to do that for you.
Here's an example:
```js
w.postMessage('start {"time_dl":"10"});
```
This starts the test with default settings, but sets the download test to last only 10 seconds.
Here's a cleaner version using ``JSON.stringify``:
```js
var params={
time_dl:10
}
w.postMessage('start '+JSON.stringify(params))
```
Notice that there is a space after the word `start`, don't forget that!
For a list of all test settings, look below, under Test parameters and Advanced test parameters. __Do not change anything if you don't know what you're doing.__
## Advanced usage
If you don't want to start from one of the examples, here's how to use the worker. Examples are still good for reference, so keep them handy.
To run the test, you need to do 3 things:
* Create the worker
* Write some code that handles the responses coming from the worker
* Write some code that handles the data coming from the worker
* Start the test
### Creating the worker
@ -78,6 +111,9 @@ w.onmessage = function (event) {
var pingStatus = data[3]
var jitterStatus = data[5]
var clientIp = data[4]
var dlProgress = data[6]
var ulProgress = data[7]
var pingProgress = data[8]
if (testState >= 4) {
clearInterval(timer) // test is finished or aborted
}
@ -89,7 +125,7 @@ w.onmessage = function (event) {
The response from the worker is composed of values separated by `;` (semicolon) in this
format:
`testState;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus`
`testState;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus;dlProgress;ulProgress;pingProgress`
* __testState__ is an integer 0-5
* `0` = Test starting
@ -117,6 +153,11 @@ format:
* Empty string (not started or aborted)
* Estimated jitter in milliseconds as a number with 2 decimals (lower = stable connection)
* The string "Fail" (test failed)
* __dlProgress__: the progress of the download test as a number between 0 and 1
* __ulProgress__: the progress of the upload test as a number between 0 and 1
* __pingProgress__: the progress of the ping+jitter test as a number between 0 and 1
Note: clientIp appears before jitterStatus. This is not a mistake, it's to keep the js file compatible with older pages from before the jitter test was introduced.
### Starting the test
To start the test with the default settings, which is usually the best choice, send the start command to the worker:
@ -130,6 +171,15 @@ If you want, you can change these settings and pass them to the worker as JSON w
```js
w.postMessage('start {"param1": "value1", "param2": "value2", ...}')
```
or this:
```js
var params{
param1:value1,
param2:value2,
...
}
w.postMessage('start '+JSON.stringify(params))
```
#### Test parameters
* __time_dl__: How long the download test should be in seconds. The test will continue regardless of this limit if the speed is still 0.00 when the limit is reached.
@ -191,13 +241,19 @@ w.postMessage('start {"param1": "value1", "param2": "value2", ...}')
* __time_ulGraceTime__: How long to wait (in seconds) before actually measuring the upload speed. This is a good idea because we want to wait for the buffers to be full (avoids the peak at the beginning of the test)
* Default: `3`
* Recommended: `>=1`
* __ping_allowPerformanceApi__: toggles use of Performance API to improve accuracy of Ping/Jitter test on browsers that support it.
* Default: `true`
* __useMebibits__: use mebibits/s instead of megabits/s for the speeds
* Default: `false`
* __overheadCompensationFactor__: compensation for HTTP and network overhead. Default value assumes typical MTUs used over the Internet. You might want to change this if you're using this in your internal network with different MTUs, or if you're using IPv6 instead of IPv4.
* Default: `1.13359567567567567568` (1048576/925000) assumes HTTP+TCP+IPv4+ETH with typical MTUs used over the Internet
* `1.0513`: HTTP+TCP+IPv6+ETH, over the Internet (empirically tested, not calculated)
* Default: `1.06` probably a decent estimate for all overhead. This was measured empirically by comparing the measured speed and the speed reported by my the network adapter.
* `1048576/925000`: old default value. This is probably too high.
* `1.0513`: HTTP+TCP+IPv6+ETH, over the Internet (empirically tested, not calculated)
* `1.0369`: Alternative value for HTTP+TCP+IPv4+ETH, over the Internet (empirically tested, not calculated)
* `1460 / 1514`: TCP+IPv4+ETH, ignoring HTTP overhead
* `1440 / 1514`: TCP+IPv6+ETH, ignoring HTTP overhead
* `1`: ignore overheads. This measures the speed at which you actually download and upload files
* `1.081`: Yet another alternative value for over the Internet (empirically tested, not calculated)
* `1514 / 1460`: TCP+IPv4+ETH, ignoring HTTP overhead
* `1514 / 1440`: TCP+IPv6+ETH, ignoring HTTP overhead
* `1`: ignore overheads. This measures the speed at which you actually download and upload files rather than the raw connection speed
### Aborting the test prematurely
The test can be aborted at any time by sending an abort command to the worker:
@ -210,22 +266,12 @@ This will terminate all network activity and stop the worker.
__Important:__ do not simply kill the worker while it's running, as it may leave pending XHR requests!
## Troubleshooting
These are the most common issues reported by users, and how to fix them
### Important notice on backwards compatibility
__Do NOT link the js file from github or fdossena.com directly into your html file. __
#### Download test gives very low result
Are garbage.php and empty.php (or your replacements) reachable?
Press F12, select network and start the test. Do you see errors? (cancelled requests are not errors)
If a small download starts, open it in a text editor. Does it say it's missing openssl_random_pseudo_bytes()? In this case, install OpenSSL (this is usually included when you install Apache and PHP on most distros).
#### Upload test is inaccurate, and I see lag spikes
Check your server's maximum POST size, make sure it's at least 20Mbytes, possibly more
#### All tests are wrong, give extremely high results, browser lags/crashes, ...
You're running the test on localhost, therefore it is trying to measure the speed of your loopback interface. The test is meant to be run over an Internet connection, from a different machine.
#### Ping test shows double the actual ping
Make sure your server is sending the ```Connection:keep-alive``` header
A lot of web developers think that referring to the latest version of a library in their project is a good thing. It is not.
Things may change and I don't want to break your project, so do yourself a favor, and keep all files on your server.
You have been warned.
## Using the test without PHP
If your server does not support PHP, or you're using something newer like Node.js, you can still use this test by replacing `garbage.php`, `empty.php` and `getIP.php` with equivalents.
@ -289,16 +335,40 @@ Example:
w.postMessage('start {"telemetry_level":"basic"}')
```
Also, see example8_telemetry.html
Also, see example-telemetry.html
### See the results
### Seeing the results
At the moment there is no front-end to see the telemetry data; you can connect to the database and see the collected results in the `speedtest_users` table.
## Troubleshooting
These are the most common issues reported by users, and how to fix them. If you still need help, contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org).
#### Download test gives very low result
Are garbage.php and empty.php (or your replacements) reachable?
Press F12, select network and start the test. Do you see errors? (cancelled requests are not errors)
If a small download starts, open it in a text editor. Does it say it's missing openssl_random_pseudo_bytes()? In this case, install OpenSSL (this is usually included when you install Apache and PHP on most distros).
#### Upload test is inaccurate, and/or I see lag spikes
Check your server's maximum POST size, make sure it's at least 20Mbytes, possibly more
#### Download and/or upload results are slightly too optimistic
The test was fine tuned to run over a typical IPv4 internet connection. If you're using it under different conditions, see the ``overheadCompensationFactor`` parameter.
#### All tests are wrong, give extremely high results, browser lags/crashes, ...
You're running the test on localhost, therefore it is trying to measure the speed of your loopback interface. The test is meant to be run over an Internet connection, from a different machine.
#### Ping test shows double the actual ping
Make sure your server is sending the ```Connection:keep-alive``` header
## Known bugs and limitations
* The ping/jitter test is measured by seeing how long it takes for an empty XHR to complete. It is not an acutal ICMP ping
* __IE11, Edge 15 and 16 (only):__ the upload test is not precise, especially on very fast connections
* __IE11:__ the upload test may not work over HTTPS
* __Firefox:__ on some Linux systems with hardware acceleration turned off, the page rendering makes the browser lag, reducing the accuracy of the ping/jitter test
### General
* The ping/jitter test is measured by seeing how long it takes for an empty XHR to complete. It is not an acutal ICMP ping. Different browsers may also show different results, especially on very fast connections on slow devices.
### IE-Specific
* The upload test is not precise on very fast connections with high latency (will probably be fixed by Edge 17)
* On IE11, a same origin policy error is erroneously triggered under unknown conditions. Seems to be related to running the test from unusual URLs like a top level domain (for instance http://abc/speedtest). These are bugs in IE11's implementation of the same origin policy, not in the speedtest itself.
* On IE11, under unknown circumstances, on some systems the test can only be run once, after which speedtest_worker.js will not be loaded by IE until the browser is restarted. This is a rare bug in IE11.
### Firefox-Specific
* On some Linux systems with hardware acceleration turned off, the page rendering makes the browser lag, reducing the accuracy of the ping/jitter test
## Making changes
Since this is an open source project, you can modify it.
@ -308,10 +378,10 @@ To make changes to the speedtest itself, edit `speedtest_worker.js`
To create the minified version, use UglifyJS like this:
```
uglifyjs -c --screw-ie8 speedtest_worker.js > speedtest_worker.min.js
uglifyjs -c speedtest_worker.js > speedtest_worker.min.js
```
Pull requests are much appreciated. If you don't use github (or git), simply contact me at dosse91@paranoici.org.
Pull requests are much appreciated. If you don't use github (or git), simply contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org).
__Important:__ please add your name to modified versions to distinguish them from the main project.
@ -321,3 +391,5 @@ This software is under the GNU LGPL license, Version 3 or newer.
To put it short: you are free to use, study, modify, and redistribute this software and modified versions of it, for free or for money.
You can also use it in proprietary software but all changes to this software must remain under the same GNU LGPL license.
Contact me at [dosse91@paranoici.org](mailto:dosse91@paranoici.org) for other licensing models.

View file

@ -1,11 +1,12 @@
<!DOCTYPE html>
<html>
<meta charset="UTF-8" />
<head>
<title>Speedtest</title>
<title>HTML5 Speedtest</title>
</head>
<body>
<h1>Speedtest</h1>
<h1>HTML5 Speedtest</h1>
<h4>IP Address</h4>
<p id="ip"></p>
@ -31,5 +32,8 @@
}
w.postMessage('start') // start the speedtest (default params. keep garbage.php and empty.dat in the same directory as the js file)
</script>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
</body>
</html>

View file

@ -1,7 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title>Speedtest</title>
<meta charset="UTF-8" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,
body {
@ -211,12 +212,12 @@
document.getElementById('testArea').style.display = 'none'
}
if (status === 1 && Number(data[1]) > 0) {
chart1.data.datasets[0].data.push(Number(data[1]))
chart1.data.datasets[0].data[~~(20*Number(data[6]))]=(Number(data[1]))
chart1.data.labels[chart1.data.datasets[0].data.length - 1] = ''
chart1.update()
}
if (status === 3 && Number(data[2]) > 0) {
chart1.data.datasets[1].data.push(Number(data[2]))
chart1.data.datasets[1].data[~~(20*Number(data[7]))]=(Number(data[2]))
chart1.data.labels[chart1.data.datasets[1].data.length - 1] = ''
chart1.update()
}
@ -238,7 +239,7 @@
</head>
<body>
<h1>Speedtest</h1>
<h1>HTML Speedtest - Chart.js example</h1>
<div id="testArea" style="display:none">
<p id="ip">Please wait...</p>
@ -251,6 +252,6 @@
<a href="javascript:abortTest()" id="abortBtn">Abort</a>
</div>
<a href="javascript:runTest()" id="startBtn">Run speedtest</a>
<br/><br/> Charts by <a href="http://www.chartjs.org/">Chart.js</a>
<br/><br/> Charts by <a href="http://www.chartjs.org/">Chart.js</a><br/><br/><a href="https://github.com/adolfintel/speedtest">Source code</a>
</body>
</html>

199
example-customSettings.html Normal file
View file

@ -0,0 +1,199 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:14em;
height:9em;
position:relative;
box-sizing:border-box;
}
div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.meterText{
position:absolute;
bottom:1.5em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
#dlText{
color:#6060AA;
}
#ulText{
color:#309030;
}
#pingText,#jitText{
color:#AA6060;
}
div.meterText:empty:before{
color:#505050 !important;
content:"0.00";
}
div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testGroup{
display:inline-block;
}
@media all and (max-width:65em){
body{
font-size:1.5vw;
}
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
div.testGroup{
display:block;
margin: 0 auto;
}
}
</style>
<script type="text/javascript">
function I(id){return document.getElementById(id);}
var w=null; //speedtest worker
var parameters={ //custom test parameters. See doc.md for a complete list
time_dl: 10, //download test lasts 10 seconds
time_ul: 10, //upload test lasts 10 seconds
count_ping: 20 //ping+jitter test does 20 pings
};
function startStop(){
if(w!=null){
//speedtest is running, abort
w.postMessage('abort');
w=null;
I("startStopBtn").className="";
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w.postMessage('start '+JSON.stringify(parameters)); //run the test with custom parameters
I("startStopBtn").className="running";
w.onmessage=function(e){
var data=e.data.split(';');
var status=Number(data[0]);
if(status>=4){
//test completed
I("startStopBtn").className="";
w=null;
}
I("ip").textContent=data[4];
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
I("pingText").textContent=data[3];
I("jitText").textContent=data[5];
};
}
}
//poll the status from the worker every 200ms (this will also update the UI)
setInterval(function(){
if(w) w.postMessage('status');
},200);
//function to (re)initialize UI
function initUI(){
I("dlText").textContent="";
I("ulText").textContent="";
I("pingText").textContent="";
I("jitText").textContent="";
I("ip").textContent="";
}
</script>
</head>
<body>
<h1>HTML5 Speedtest - Custom settings example</h1>
<div id="startStopBtn" onclick="startStop()"></div>
<div id="test">
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
</div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Ping</div>
<div id="pingText" class="meterText"></div>
<div class="unit">ms</div>
</div>
<div class="testArea">
<div class="testName">Jitter</div>
<div id="jitText" class="meterText"></div>
<div class="unit">ms</div>
</div>
</div>
<div id="ipArea">
IP Address: <span id="ip"></span>
</div>
</div>
<div>Custom parameters: <span id="params"></span><script type="text/javascript">I("params").textContent=JSON.stringify(parameters)</script></div>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">initUI();</script>
</body>
</html>

View file

@ -0,0 +1,172 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:14em;
height:9em;
position:relative;
box-sizing:border-box;
}
div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.meterText{
position:absolute;
bottom:1.5em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
#dlText{
color:#6060AA;
}
#ulText{
color:#309030;
}
#pingText,#jitText{
color:#AA6060;
}
div.meterText:empty:before{
color:#505050 !important;
content:"0.00";
}
div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testGroup{
display:inline-block;
}
@media all and (max-width:65em){
body{
font-size:2vw;
}
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
div.testGroup{
display:block;
margin: 0 auto;
}
}
</style>
<script type="text/javascript">
function I(id){return document.getElementById(id);}
var w=null; //speedtest worker
function startStop(){
if(w!=null){
//speedtest is running, abort
w.postMessage('abort');
w=null;
I("startStopBtn").className="";
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w.postMessage('start {"test_order":"D_U"}'); //run only download and upload tests, with a 1s pause in between
I("startStopBtn").className="running";
w.onmessage=function(e){
var data=e.data.split(';');
var status=Number(data[0]);
if(status>=4){
//test completed
I("startStopBtn").className="";
w=null;
}
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
};
}
}
//poll the status from the worker every 200ms (this will also update the UI)
setInterval(function(){
if(w) w.postMessage('status');
},200);
//function to (re)initialize UI
function initUI(){
I("dlText").textContent="";
I("ulText").textContent="";
}
</script>
</head>
<body>
<h1>HTML5 Speedtest - Custom settings example</h1>
<div id="startStopBtn" onclick="startStop()"></div>
<div id="test">
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
</div>
</div>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">initUI();</script>
</body>
</html>

259
example-gauges.html Normal file
View file

@ -0,0 +1,259 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:16em;
height:12.5em;
position:relative;
box-sizing:border-box;
}
div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.meterText{
position:absolute;
bottom:1.55em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
div.meterText:empty:before{
content:"0.00";
}
div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testArea canvas{
position:absolute;
top:0; left:0; width:100%; height:100%;
z-index:1;
}
div.testGroup{
display:inline-block;
}
@media all and (max-width:65em){
body{
font-size:1.5vw;
}
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
div.testGroup{
display:block;
margin: 0 auto;
}
}
</style>
<script type="text/javascript">
function I(id){return document.getElementById(id);}
var meterBk="#E0E0E0";
var dlColor="#6060AA",
ulColor="#309030",
pingColor="#AA6060",
jitColor="#AA6060";
var progColor="#EEEEEE";
//CODE FOR GAUGES
function drawMeter(c,amount,bk,fg,progress,prog){
var ctx=c.getContext("2d");
var dp=window.devicePixelRatio||1;
var cw=c.clientWidth*dp, ch=c.clientHeight*dp;
var sizScale=ch*0.0055;
if(c.width==cw&&c.height==ch){
ctx.clearRect(0,0,cw,ch);
}else{
c.width=cw;
c.height=ch;
}
ctx.beginPath();
ctx.strokeStyle=bk;
ctx.lineWidth=16*sizScale;
ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,Math.PI*0.1);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle=fg;
ctx.lineWidth=16*sizScale;
ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,amount*Math.PI*1.2-Math.PI*1.1);
ctx.stroke();
if(typeof progress !== "undefined"){
ctx.fillStyle=prog;
ctx.fillRect(c.width*0.3,c.height-16*sizScale,c.width*0.4*progress,4*sizScale);
}
}
function mbpsToAmount(s){
return 1-(1/(Math.pow(1.3,Math.sqrt(s))));
}
function msToAmount(s){
return 1-(1/(Math.pow(1.08,Math.sqrt(s))));
}
//SPEEDTEST AND UI CODE
var w=null; //speedtest worker
var data=null; //data from worker
function startStop(){
if(w!=null){
//speedtest is running, abort
w.postMessage('abort');
w=null;
data=null;
I("startStopBtn").className="";
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w.postMessage('start'); //Add optional parameters as a JSON object to this command
I("startStopBtn").className="running";
w.onmessage=function(e){
data=e.data.split(';');
var status=Number(data[0]);
if(status>=4){
//test completed
I("startStopBtn").className="";
w=null;
updateUI(true);
}
};
}
}
//this function reads the data sent back by the worker and updates the UI
function updateUI(forced){
if(!forced&&(!data||!w)) return;
var status=Number(data[0]);
I("ip").textContent=data[4];
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
drawMeter(I("dlMeter"),mbpsToAmount(Number(data[1]*(status==1?oscillate():1))),meterBk,dlColor,Number(data[6]),progColor);
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
drawMeter(I("ulMeter"),mbpsToAmount(Number(data[2]*(status==3?oscillate():1))),meterBk,ulColor,Number(data[7]),progColor);
I("pingText").textContent=data[3];
drawMeter(I("pingMeter"),msToAmount(Number(data[3]*(status==2?oscillate():1))),meterBk,pingColor,Number(data[8]),progColor);
I("jitText").textContent=data[5];
drawMeter(I("jitMeter"),msToAmount(Number(data[5]*(status==2?oscillate():1))),meterBk,jitColor,Number(data[8]),progColor);
}
function oscillate(){
return 1+0.02*Math.sin(Date.now()/100);
}
//poll the status from the worker (this will call updateUI)
setInterval(function(){
if(w) w.postMessage('status');
},200);
//update the UI every frame
window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||(function(callback,element){setTimeout(callback,1000/60);});
function frame(){
requestAnimationFrame(frame);
updateUI();
}
frame(); //start frame loop
//function to (re)initialize UI
function initUI(){
drawMeter(I("dlMeter"),0,meterBk,dlColor,0);
drawMeter(I("ulMeter"),0,meterBk,ulColor,0);
drawMeter(I("pingMeter"),0,meterBk,pingColor,0);
drawMeter(I("jitMeter"),0,meterBk,jitColor,0);
I("dlText").textContent="";
I("ulText").textContent="";
I("pingText").textContent="";
I("jitText").textContent="";
I("ip").textContent="";
}
</script>
</head>
<body>
<h1>HTML5 Speedtest</h1>
<div id="startStopBtn" onclick="startStop()"></div>
<div id="test">
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<canvas id="dlMeter" class="meter"></canvas>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<canvas id="ulMeter" class="meter"></canvas>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
</div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Ping</div>
<canvas id="pingMeter" class="meter"></canvas>
<div id="pingText" class="meterText"></div>
<div class="unit">ms</div>
</div>
<div class="testArea">
<div class="testName">Jitter</div>
<canvas id="jitMeter" class="meter"></canvas>
<div id="jitText" class="meterText"></div>
<div class="unit">ms</div>
</div>
</div>
<div id="ipArea">
IP Address: <span id="ip"></span>
</div>
</div>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">setTimeout(initUI,100);</script>
</body>
</html>

193
example-pretty.html Normal file
View file

@ -0,0 +1,193 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:14em;
height:9em;
position:relative;
box-sizing:border-box;
}
div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.meterText{
position:absolute;
bottom:1.5em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
#dlText{
color:#6060AA;
}
#ulText{
color:#309030;
}
#pingText,#jitText{
color:#AA6060;
}
div.meterText:empty:before{
color:#505050 !important;
content:"0.00";
}
div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testGroup{
display:inline-block;
}
@media all and (max-width:65em){
body{
font-size:1.5vw;
}
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
div.testGroup{
display:block;
margin: 0 auto;
}
}
</style>
<script type="text/javascript">
function I(id){return document.getElementById(id);}
var w=null; //speedtest worker
function startStop(){
if(w!=null){
//speedtest is running, abort
w.postMessage('abort');
w=null;
I("startStopBtn").className="";
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w.postMessage('start'); //Add optional parameters as a JSON object to this command
I("startStopBtn").className="running";
w.onmessage=function(e){
var data=e.data.split(';');
var status=Number(data[0]);
if(status>=4){
//test completed
I("startStopBtn").className="";
w=null;
}
I("ip").textContent=data[4];
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
I("pingText").textContent=data[3];
I("jitText").textContent=data[5];
};
}
}
//poll the status from the worker every 200ms (this will also update the UI)
setInterval(function(){
if(w) w.postMessage('status');
},200);
//function to (re)initialize UI
function initUI(){
I("dlText").textContent="";
I("ulText").textContent="";
I("pingText").textContent="";
I("jitText").textContent="";
I("ip").textContent="";
}
</script>
</head>
<body>
<h1>HTML5 Speedtest</h1>
<div id="startStopBtn" onclick="startStop()"></div>
<div id="test">
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
</div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Ping</div>
<div id="pingText" class="meterText"></div>
<div class="unit">ms</div>
</div>
<div class="testArea">
<div class="testName">Jitter</div>
<div id="jitText" class="meterText"></div>
<div class="unit">ms</div>
</div>
</div>
<div id="ipArea">
IP Address: <span id="ip"></span>
</div>
</div>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">initUI();</script>
</body>
</html>

215
example-progressBar.html Normal file
View file

@ -0,0 +1,215 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:14em;
height:9em;
position:relative;
box-sizing:border-box;
}
div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.meterText{
position:absolute;
bottom:1.5em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
#dlText{
color:#6060AA;
}
#ulText{
color:#309030;
}
#pingText,#jitText{
color:#AA6060;
}
div.meterText:empty:before{
color:#505050 !important;
content:"0.00";
}
div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testGroup{
display:inline-block;
}
@media all and (max-width:65em){
body{
font-size:1.5vw;
}
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
div.testGroup{
display:block;
margin: 0 auto;
}
}
#progressBar{
width:90%;
height:0.3em;
background-color:#EEEEEE;
position:relative;
display:block;
margin:0 auto;
margin-bottom:2em;
}
#progress{
position:absolute;
top:0; left:0;
height:100%;
width:0%;
transition: width 2s;
background-color:#90BBFF;
}
</style>
<script type="text/javascript">
function I(id){return document.getElementById(id);}
var w=null; //speedtest worker
function startStop(){
if(w!=null){
//speedtest is running, abort
w.postMessage('abort');
w=null;
I("startStopBtn").className="";
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w.postMessage('start'); //Add optional parameters as a JSON object to this command
I("startStopBtn").className="running";
w.onmessage=function(e){
var data=e.data.split(';');
var status=Number(data[0]);
if(status>=4){
//test completed
I("startStopBtn").className="";
w=null;
}
I("ip").textContent=data[4];
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
I("pingText").textContent=data[3];
I("jitText").textContent=data[5];
var prog=(Number(data[6])*2+Number(data[7])*2+Number(data[8]))/5;
I("progress").style.width=(100*prog)+"%";
};
}
}
//poll the status from the worker every 200ms (this will also update the UI)
setInterval(function(){
if(w) w.postMessage('status');
},200);
//function to (re)initialize UI
function initUI(){
I("dlText").textContent="";
I("ulText").textContent="";
I("pingText").textContent="";
I("jitText").textContent="";
I("ip").textContent="";
I("progress").style.width="";
}
</script>
</head>
<body>
<h1>HTML5 Speedtest</h1>
<div id="startStopBtn" onclick="startStop()"></div>
<div id="test">
<div id="progressBar"><div id="progress"></div></div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
</div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Ping</div>
<div id="pingText" class="meterText"></div>
<div class="unit">ms</div>
</div>
<div class="testArea">
<div class="testName">Jitter</div>
<div id="jitText" class="meterText"></div>
<div class="unit">ms</div>
</div>
</div>
<div id="ipArea">
IP Address: <span id="ip"></span>
</div>
</div>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">initUI();</script>
</body>
</html>

View file

@ -0,0 +1,194 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>HTML5 Speedtest</title>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:14em;
height:9em;
position:relative;
box-sizing:border-box;
}
div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.meterText{
position:absolute;
bottom:1.5em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
#dlText{
color:#6060AA;
}
#ulText{
color:#309030;
}
#pingText,#jitText{
color:#AA6060;
}
div.meterText:empty:before{
color:#505050 !important;
content:"0.00";
}
div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testGroup{
display:inline-block;
}
@media all and (max-width:65em){
body{
font-size:1.5vw;
}
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
div.testGroup{
display:block;
margin: 0 auto;
}
}
</style>
<script type="text/javascript">
function I(id){return document.getElementById(id);}
var w=null; //speedtest worker
function startStop(){
if(w!=null){
//speedtest is running, abort
w.postMessage('abort');
w=null;
I("startStopBtn").className="";
initUI();
}else{
//test is not running, begin
w=new Worker('speedtest_worker.min.js');
w.postMessage('start {"telemetry_level":"basic"}'); //Add optional parameters (see doc.md)
I("startStopBtn").className="running";
w.onmessage=function(e){
var data=e.data.split(';');
var status=Number(data[0]);
if(status>=4){
//test completed
I("startStopBtn").className="";
w=null;
}
I("ip").textContent=data[4];
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
I("pingText").textContent=data[3];
I("jitText").textContent=data[5];
};
}
}
//poll the status from the worker every 200ms (this will also update the UI)
setInterval(function(){
if(w) w.postMessage('status');
},200);
//function to (re)initialize UI
function initUI(){
I("dlText").textContent="";
I("ulText").textContent="";
I("pingText").textContent="";
I("jitText").textContent="";
I("ip").textContent="";
}
</script>
</head>
<body>
<h1>HTML5 Speedtest - Telemetry example</h1>
<div id="startStopBtn" onclick="startStop()"></div>
<div id="test">
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbps</div>
</div>
</div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Ping</div>
<div id="pingText" class="meterText"></div>
<div class="unit">ms</div>
</div>
<div class="testArea">
<div class="testName">Jitter</div>
<div id="jitText" class="meterText"></div>
<div class="unit">ms</div>
</div>
</div>
<div id="ipArea">
IP Address: <span id="ip"></span>
</div>
</div>
<div>Basic telemetry is active; results will be saved in your database, without the full log. If the results don't appear, check the settings in telemetry.php</div>
<a href="https://github.com/adolfintel/speedtest">Source code</a>
<script type="text/javascript">initUI();</script>
</body>
</html>

View file

@ -1,91 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Speedtest</title>
<style type="text/css">
html,
body {
margin: 0;
padding: 0;
border: none;
text-align: center;
}
div.test {
display: inline-block;
margin: 1em;
text-align: center;
}
div.testName,
div.meterUnit {
font-size: 3vw;
}
div.meter {
font-size: 6vw;
line-height: 1.5em;
height: 1.5em !important;
}
.flash {
animation: flash 0.6s linear infinite;
}
@keyframes flash {
0% { opacity: 0.6; }
50% { opacity: 1; }
}
</style>
</head>
<body>
<h1>Speedtest</h1>
<div class="test">
<div class="testName">Download</div>
<div class="meter">&nbsp;<span id="download"></span>&nbsp;</div>
<div class="meterUnit">Mbit/s</div>
</div>
<div class="test">
<div class="testName">Upload</div>
<div class="meter">&nbsp;<span id="upload"></span>&nbsp;</div>
<div class="meterUnit">Mbit/s</div>
</div>
<div class="test">
<div class="testName">Latency</div>
<div class="meter">&nbsp;<span id="ping"></span>&nbsp;</div>
<div class="meterUnit">ms</div>
</div>
<div class="test">
<div class="testName">Jitter</div>
<div class="meter">&nbsp;<span id="jitter"></span>&nbsp;</div>
<div class="meterUnit">ms</div>
</div>
<div id="ip"></div>
<script type="text/javascript">
var w = new Worker('speedtest_worker.min.js')
var interval = setInterval(function () { w.postMessage('status') }, 100)
w.onmessage = function (event) {
var data = event.data.split(';')
var status = Number(data[0])
var dl = document.getElementById('download')
var ul = document.getElementById('upload')
var ping = document.getElementById('ping')
var ip = document.getElementById('ip')
var jitter = document.getElementById('jitter')
dl.className = status === 1 ? 'flash' : ''
ping.className = status === 2 ? 'flash' : ''
jitter.className = ul.className = status === 3 ? 'flash' : ''
if (status >= 4) {
clearInterval(interval)
}
dl.textContent = data[1]
ul.textContent = data[2]
ping.textContent = data[3]
jitter.textContent = data[5]
ip.textContent = 'Your IP: ' + data[4]
}
w.postMessage('start {"url_dl": "garbage.php", "url_ul": "empty.php", "url_ping": "empty.php", "time_dl": "10", "time_ul": "15", "count_ping": "30"}') // start with custom parameters. paths are relative to js file. you can omit parameters that you don't want to change
</script>
</body>
</html>

View file

@ -1,133 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Speedtest</title>
<style type="text/css">
html,
body {
margin: 0;
padding: 0;
border: none;
text-align: center;
}
div.test {
display: inline-block;
margin: 1em;
font-size: 2vw;
min-width: 20vw;
text-align: center;
}
div.testName,
div.meterUnit {
font-size: 1em;
}
div.meter {
font-size: 1.5em;
line-height: 1.5em;
height: 2em !important;
}
.flash {
animation: flash 0.6s linear infinite;
}
@keyframes flash {
0% { opacity: 0.6; }
50% { opacity: 1; }
}
a {
display: inline-block;
border: 0.15em solid #000000;
padding: 0.3em 0.5em;
margin: 0.6em;
color: #000000;
text-decoration: none;
}
#ip {
margin: 0.8em 0;
font-size: 1.2em;
}
@media all and (max-width: 50em) {
div.test {
font-size: 2em;
}
}
</style>
<script type="text/javascript">
var w = null
function runTest() {
document.getElementById('startBtn').style.display = 'none'
document.getElementById('testArea').style.display = ''
document.getElementById('abortBtn').style.display = ''
w = new Worker('speedtest_worker.min.js')
var interval = setInterval(function () { w.postMessage('status') }, 100)
w.onmessage = function (event) {
var data = event.data.split(';')
var status = Number(data[0])
var dl = document.getElementById('download')
var ul = document.getElementById('upload')
var ping = document.getElementById('ping')
var ip = document.getElementById('ip')
var jitter = document.getElementById('jitter')
dl.className = status === 1 ? 'flash' : ''
ping.className = status === 2 ? 'flash' : ''
jitter.className = ul.className = status === 3 ? 'flash' : ''
if (status >= 4) {
clearInterval(interval)
document.getElementById('abortBtn').style.display = 'none'
document.getElementById('startBtn').style.display = ''
w = null
}
if (status === 5) {
document.getElementById('testArea').style.display = 'none'
}
dl.textContent = data[1]
ul.textContent = data[2]
ping.textContent = data[3]
jitter.textContent = data[5]
ip.textContent = data[4]
}
w.postMessage('start')
}
function abortTest() {
if (w) w.postMessage('abort')
}
</script>
</head>
<body>
<h1>Speedtest</h1>
<div id="testArea" style="display:none">
<div id="ip">Please wait...</div>
<div class="test">
<div class="testName">Download</div>
<div class="meter">&nbsp;<span id="download"></span>&nbsp;</div>
<div class="meterUnit">Mbit/s</div>
</div>
<div class="test">
<div class="testName">Upload</div>
<div class="meter">&nbsp;<span id="upload"></span>&nbsp;</div>
<div class="meterUnit">Mbit/s</div>
</div>
<div class="test">
<div class="testName">Latency</div>
<div class="meter">&nbsp;<span id="ping"></span>&nbsp;</div>
<div class="meterUnit">ms</div>
</div>
<div class="test">
<div class="testName">Jitter</div>
<div class="meter">&nbsp;<span id="jitter"></span>&nbsp;</div>
<div class="meterUnit">ms</div>
</div>
<br/>
<a href="javascript:abortTest()" id="abortBtn">Abort</a>
</div>
<a href="javascript:runTest()" id="startBtn">Run speedtest</a>
</body>
</html>

View file

@ -1,197 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Speedtest</title>
<style type="text/css">
html,
body {
margin: 0;
padding: 0;
border: none;
text-align: center;
font-family: 'Open Sans';
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Roboto', sans-serif;
font-weight: 700;
}
div.meter {
display: inline-block;
height: 300px;
width: 400px;
text-align: center;
font-size: 6vw;
}
div#testArea {
display: flex;
justify-content: center;
flex-flow: row wrap;
}
a {
text-decoration: none;
}
.button {
display: inline-block;
margin: 10px 5px 0 2px;
padding: 16px 40px;
border-radius: 5px;
font-size: 18px;
border: none;
background: #34aadc;
color: white;
cursor: pointer;
text-transform: uppercase;
font-weight: 700;
font-family: 'Roboto';
}
#ip {
margin: 1em 0;
font-size: 1.2em;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.4/raphael-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/justgage/1.2.2/justgage.min.js"></script>
<script type="text/javascript">
var w = null
var ggdl, ggul, ggping
function runTest() {
w = new Worker('speedtest_worker.min.js')
var interval = setInterval(function () { w.postMessage('status') }, 100)
document.getElementById('abortBtn').style.display = ''
document.getElementById('startBtn').style.display = 'none'
w.onmessage = function (event) {
var data = event.data.split(';')
var status = Number(data[0])
if (status >= 4) {
clearInterval(interval)
document.getElementById('abortBtn').style.display = 'none'
document.getElementById('startBtn').style.display = ''
w = null
}
updateGauge(ggdl, data[1])
updateGauge(ggul, data[2])
updateGauge(ggping, data[3])
document.getElementById('ip').textContent = 'Your IP: ' + data[4]
updateGauge(ggjitter, data[5])
}
w.postMessage('start {"time_ul": "10", "time_dl": "10", "count_ping": "50", "url_dl": "garbage.php", "url_ul": "empty.php", "url_ping": "empty.php", "url_getIp": "getIP.php"}')
}
function abortTest() {
if (w) w.postMessage('abort')
}
document.addEventListener('DOMContentLoaded', function (event) {
ggdl = new JustGage({
id: 'ggdl',
title: 'Download',
label: 'Mbit/s',
titleFontFamily: 'Open Sans',
valueFontFamily: 'Open Sans',
refreshAnimationTime: 300,
value: 0,
min: 0,
max: 10,
decimals: 2,
formatNumber: true,
humanFriendly: false,
levelColors: [
'#999999',
'#339933'
]
})
ggul = new JustGage({
id: 'ggul',
title: 'Upload',
label: 'Mbit/s',
titleFontFamily: 'Open Sans',
valueFontFamily: 'Open Sans',
refreshAnimationTime: 300,
value: 0,
min: 0,
max: 10,
decimals: 2,
formatNumber: true,
humanFriendly: false,
levelColors: [
'#999999',
'#333399'
]
})
ggping = new JustGage({
id: 'ggping',
title: 'Ping',
label: 'ms',
titleFontFamily: 'Open Sans',
valueFontFamily: 'Open Sans',
refreshAnimationTime: 300,
value: 0,
min: 0,
max: 100,
decimals: 2,
formatNumber: true,
humanFriendly: false,
levelColors: [
'#999999',
'#993333'
]
})
ggjitter = new JustGage({
id: 'ggjitter',
title: 'Jitter',
label: 'ms',
titleFontFamily: 'Open Sans',
valueFontFamily: 'Open Sans',
refreshAnimationTime: 300,
value: 0,
min: 0,
max: 100,
decimals: 2,
formatNumber: true,
humanFriendly: false,
levelColors: [
'#999999',
'#993333'
]
})
})
function updateGauge(gauge, value) {
// Alway use next power of 2 as maximum
var max = Math.max(Math.pow(2, Math.ceil(Math.log2(value))), gauge.config.max)
// Refresh the gauge
gauge.refresh(value, max)
}
</script>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,500,700|Roboto:400,500,700" rel="stylesheet">
</head>
<body>
<h1>Speed Test</h1>
<div id="testArea">
<div class="meter" id="ggdl"></div>
<div class="meter" id="ggul"></div>
<div class="meter" id="ggping"></div>
<div class="meter" id="ggjitter"></div>
</div>
<div id="ip"></div>
<div>
<a href="javascript:runTest()" id="startBtn" class="button">Start</a>
<a href="javascript:abortTest()" id="abortBtn" class="button" style="display:none;">Abort</a>
</div>
<p>Fonts: <a href="https://fonts.google.com/">Google Fonts</a> | Gauges: <a href="http://justgage.com/">justgage.com</a></p>
</body>
</html>

View file

@ -1,104 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>Speedtest</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<style type="text/css">
.st-block {
text-align: center;
}
.st-btn {
margin-top: -0.5rem;
margin-left: 1.5rem;
}
.st-value>span:empty::before {
content: "0.00";
color: #636c72;
}
#st-ip:empty::before {
content: "___.___.___.___";
color: #636c72;
}
</style>
</head>
<body class="my-4">
<div class="container">
<div class="row">
<div class="col-sm-12 mb-3">
<p class="h1">
Speedtest
<button id="st-start" class="btn btn-outline-primary st-btn" onclick="startTest()">Start</button>
<button id="st-stop" class="btn btn-danger st-btn" onclick="stopTest()" hidden="true">Stop</button>
</p>
<p class="lead">
Your IP: <span id="st-ip"></span>
</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Download</h3>
<p class="display-4 st-value"><span id="st-download"></span></p>
<p class="lead">Mbit/s</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Upload</h3>
<p class="display-4 st-value"><span id="st-upload"></span></p>
<p class="lead">Mbit/s</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Ping</h3>
<p class="display-4 st-value"><span id="st-ping"></span></p>
<p class="lead">ms</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Jitter</h3>
<p class="display-4 st-value"><span id="st-jitter"></span></p>
<p class="lead">ms</p>
</div>
</div>
</div>
<script type="text/javascript">
var worker = null
function startTest() {
document.getElementById('st-start').hidden = true
document.getElementById('st-stop').hidden = false
worker = new Worker('speedtest_worker.min.js')
var interval = setInterval(function () { worker.postMessage('status') }, 100)
worker.onmessage = function (event) {
var download = document.getElementById('st-download')
var upload = document.getElementById('st-upload')
var ping = document.getElementById('st-ping')
var jitter = document.getElementById('st-jitter')
var ip = document.getElementById('st-ip')
var data = event.data.split(';')
var status = Number(data[0])
if (status >= 4) {
clearInterval(interval)
document.getElementById('st-start').hidden = false
document.getElementById('st-stop').hidden = true
w = null
}
if (status === 5) {
// speedtest cancelled, clear output data
data = []
}
download.textContent = (status==1&&data[1]==0)?"Starting":data[1]
upload.textContent = (status==3&&data[2]==0)?"Starting":data[2]
ping.textContent = data[3]
ip.textContent = data[4]
jitter.textContent = data[5]
}
worker.postMessage('start')
}
function stopTest() {
if (worker) worker.postMessage('abort')
}
</script>
</body>
</html>

View file

@ -1,116 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>Speedtest</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<style type="text/css">
.st-block {
text-align: center;
}
.st-btn {
margin-top: -0.5rem;
margin-left: 1.5rem;
}
.st-value>span:empty::before {
content: "0.00";
color: #636c72;
}
#st-ip:empty::before {
content: "___.___.___.___";
color: #636c72;
}
</style>
</head>
<body class="my-4">
<div class="container">
<div class="row">
<div class="col-sm-12 mb-3">
<p class="h1">
Speedtest
<button id="st-start" class="btn btn-outline-primary st-btn" onclick="startTest()">Start</button>
<button id="st-stop" class="btn btn-danger st-btn" onclick="stopTest()" hidden="true">Stop</button>
</p>
<p class="lead">
Your IP: <span id="st-ip"></span>
<input type="checkbox" id="st-ip-checkbox">
</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Download</h3>
<p class="display-4 st-value"><span id="st-download"></span></p>
<p class="lead">Mbit/s</p>
<p><input type="checkbox" id="st-download-checkbox"></p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Upload</h3>
<p class="display-4 st-value"><span id="st-upload"></span></p>
<p class="lead">Mbit/s</p>
<p><input type="checkbox" id="st-upload-checkbox"></p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Ping</h3>
<p class="display-4 st-value"><span id="st-ping"></span></p>
<p class="lead">ms</p>
<p><input type="checkbox" id="st-ping-checkbox" checked></p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Jitter</h3>
<p class="display-4 st-value"><span id="st-jitter"></span></p>
<p class="lead">ms</p>
</div>
</div>
</div>
<script type="text/javascript">
var worker = null
function startTest() {
document.getElementById('st-start').hidden = true
document.getElementById('st-stop').hidden = false
worker = new Worker('speedtest_worker.min.js')
var interval = setInterval(function () { worker.postMessage('status') }, 100)
worker.onmessage = function (event) {
var download = document.getElementById('st-download')
var upload = document.getElementById('st-upload')
var ping = document.getElementById('st-ping')
var jitter = document.getElementById('st-jitter')
var ip = document.getElementById('st-ip')
var data = event.data.split(';')
var status = Number(data[0])
if (status >= 4) {
clearInterval(interval)
document.getElementById('st-start').hidden = false
document.getElementById('st-stop').hidden = true
w = null
}
if (status === 5) {
// speedtest cancelled, clear output data
data = []
}
download.textContent = (status==1&&data[1]==0)?"Starting":data[1]
upload.textContent = (status==3&&data[2]==0)?"Starting":data[2]
ping.textContent = data[3]
ip.textContent = data[4]
jitter.textContent = data[5]
}
var ip_checkbox = document.getElementById("st-ip-checkbox")
var dl_checkbox = document.getElementById("st-download-checkbox")
var ul_checkbox = document.getElementById("st-upload-checkbox")
var ping_checkbox = document.getElementById("st-ping-checkbox")
var test_order=(ip_checkbox.checked?"I":"")+(dl_checkbox.checked?"D":"")+(ul_checkbox.checked?"U":"")+(ping_checkbox.checked?"P":"")
worker.postMessage('start {"test_order":"'+test_order+'" }')
}
function stopTest() {
if (worker) worker.postMessage('abort')
}
</script>
</body>
</html>

View file

@ -1,105 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<title>Speedtest</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<style type="text/css">
.st-block {
text-align: center;
}
.st-btn {
margin-top: -0.5rem;
margin-left: 1.5rem;
}
.st-value>span:empty::before {
content: "0.00";
color: #636c72;
}
#st-ip:empty::before {
content: "___.___.___.___";
color: #636c72;
}
</style>
</head>
<body class="my-4">
<div class="container">
<div class="row">
<div class="col-sm-12 mb-3">
<p class="h1">
Speedtest
<button id="st-start" class="btn btn-outline-primary st-btn" onclick="startTest()">Start</button>
<button id="st-stop" class="btn btn-danger st-btn" onclick="stopTest()" hidden="true">Stop</button>
<p>Basic telemetry is active; results will be saved in your database. If the results don't appear, check the settings in telemetry.php</p>
</p>
<p class="lead">
Your IP: <span id="st-ip"></span>
</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Download</h3>
<p class="display-4 st-value"><span id="st-download"></span></p>
<p class="lead">Mbit/s</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Upload</h3>
<p class="display-4 st-value"><span id="st-upload"></span></p>
<p class="lead">Mbit/s</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Ping</h3>
<p class="display-4 st-value"><span id="st-ping"></span></p>
<p class="lead">ms</p>
</div>
<div class="col-lg-3 col-md-6 mb-3 st-block">
<h3>Jitter</h3>
<p class="display-4 st-value"><span id="st-jitter"></span></p>
<p class="lead">ms</p>
</div>
</div>
</div>
<script type="text/javascript">
var worker = null
function startTest() {
document.getElementById('st-start').hidden = true
document.getElementById('st-stop').hidden = false
worker = new Worker('speedtest_worker.min.js')
var interval = setInterval(function () { worker.postMessage('status') }, 100)
worker.onmessage = function (event) {
var download = document.getElementById('st-download')
var upload = document.getElementById('st-upload')
var ping = document.getElementById('st-ping')
var jitter = document.getElementById('st-jitter')
var ip = document.getElementById('st-ip')
var data = event.data.split(';')
var status = Number(data[0])
if (status >= 4) {
clearInterval(interval)
document.getElementById('st-start').hidden = false
document.getElementById('st-stop').hidden = true
w = null
}
if (status === 5) {
// speedtest cancelled, clear output data
data = []
}
download.textContent = (status==1&&data[1]==0)?"Starting":data[1]
upload.textContent = (status==3&&data[2]==0)?"Starting":data[2]
ping.textContent = data[3]
ip.textContent = data[4]
jitter.textContent = data[5]
}
worker.postMessage('start {"telemetry_level":"basic"}')
}
function stopTest() {
if (worker) worker.postMessage('abort')
}
</script>
</body>
</html>

View file

@ -1,3 +1,4 @@
<?php
header('Content-Type: text/plain; charset=utf-8');
echo $_SERVER['REMOTE_ADDR'];
?>

View file

@ -1,5 +1,5 @@
/*
HTML5 Speedtest v4.4
HTML5 Speedtest v4.5
by Federico Dossena
https://github.com/adolfintel/speedtest/
GNU LGPLv3 License
@ -12,6 +12,9 @@ var ulStatus = '' // upload speed in megabit/s with 2 decimal digits
var pingStatus = '' // ping in milliseconds with 2 decimal digits
var jitterStatus = '' // jitter in milliseconds with 2 decimal digits
var clientIp = '' // client's IP address as reported by getIP.php
var dlProgress = 0 //progress of download test 0-1
var ulProgress = 0 //progress of upload test 0-1
var pingProgress = 0 //progress of ping+jitter test 0-1
var log='' //telemetry log
function tlog(s){log+=Date.now()+': '+s+'\n'}
@ -35,7 +38,9 @@ var settings = {
xhr_dlUseBlob: false, // if set to true, it reduces ram usage but uses the hard drive (useful with large garbagePhp_chunkSize and/or high xhr_dlMultistream)
garbagePhp_chunkSize: 20, // size of chunks sent by garbage.php (can be different if enable_quirks is active)
enable_quirks: true, // enable quirks for specific browsers. currently it overrides settings to optimize for specific browsers, unless they are already being overridden with the start command
overheadCompensationFactor: 1048576/925000, //compensation for HTTP+TCP+IP+ETH overhead. 925000 is how much data is actually carried over 1048576 (1mb) bytes downloaded/uploaded. This default value assumes HTTP+TCP+IPv4+ETH with typical MTUs over the Internet. You may want to change this if you're going through your local network with a different MTU or if you're going over IPv6 (see doc.md for some other values)
ping_allowPerformanceApi: true, // if enabled, the ping test will attempt to calculate the ping more precisely using the Performance API. Currently works perfectly in Chrome, badly in Edge, and not at all in Firefox. If Performance API is not supported or the result is obviously wrong, a fallback is provided.
overheadCompensationFactor: 1.06, //can be changed to compensatie for transport overhead. (see doc.md for some other values)
useMebibits: false, //if set to true, speed will be reported in mebibits/s instead of megabits/s
telemetry_level: 0, // 0=disabled, 1=basic (results only), 2=full (results+log)
url_telemetry: 'telemetry.php' // path to the script that adds telemetry data to the database
}
@ -52,7 +57,7 @@ function url_sep (url) { return url.match(/\?/) ? '&' : '?'; }
/*
listener for commands from main thread to this worker.
commands:
-status: returns the current status as a string of values spearated by a semicolon (;) in this order: testStatus;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus
-status: returns the current status as a string of values spearated by a semicolon (;) in this order: testStatus;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus;dlProgress;ulProgress;pingProgress
-abort: aborts the current test
-start: starts the test. optionally, settings can be passed as JSON.
example: start {"time_ul":"10", "time_dl":"10", "count_ping":"50"}
@ -60,7 +65,7 @@ function url_sep (url) { return url.match(/\?/) ? '&' : '?'; }
this.addEventListener('message', function (e) {
var params = e.data.split(' ')
if (params[0] === 'status') { // return status
postMessage(testStatus + ';' + dlStatus + ';' + ulStatus + ';' + pingStatus + ';' + clientIp + ';' + jitterStatus)
postMessage(testStatus + ';' + dlStatus + ';' + ulStatus + ';' + pingStatus + ';' + clientIp + ';' + jitterStatus + ';' + dlProgress + ';' + ulProgress + ';' + pingProgress)
}
if (params[0] === 'start' && testStatus === 0) { // start new test
testStatus = 1
@ -93,10 +98,9 @@ this.addEventListener('message', function (e) {
// edge more precise with 3 download streams
settings.xhr_dlMultistream = 3
}
if (/Edge\/15.(\d+)/i.test(ua) || /Edge\/16.(\d+)/i.test(ua)) {
//Edge 15 introduced a bug that causes onprogress events to not get fired, so for Edge 15, we have to use the "small chunks" workaround that reduces accuracy
settings.forceIE11Workaround = true
}
//Edge 15 introduced a bug that causes onprogress events to not get fired, we have to use the "small chunks" workaround that reduces accuracy
//TODO: MOVE OUT OF QUIRKS!
settings.forceIE11Workaround = true
}
if (/Chrome.(\d+)/i.test(ua) && (!!self.fetch)) {
if(typeof s.xhr_dlMultistream === 'undefined'){
@ -113,13 +117,14 @@ this.addEventListener('message', function (e) {
// run the tests
tlog(JSON.stringify(settings))
test_pointer=0;
var iRun=false,dRun=false,uRun=false,pRun=false;
var runNextTest=function(){
if(test_pointer>=settings.test_order.length){testStatus=4; sendTelemetry(); return;}
switch(settings.test_order.charAt(test_pointer)){
case 'I':{test_pointer++; getIp(runNextTest);} break;
case 'D':{test_pointer++; testStatus=1; dlTest(runNextTest);} break;
case 'U':{test_pointer++; testStatus=3; ulTest(runNextTest);} break;
case 'P':{test_pointer++; testStatus=2; pingTest(runNextTest);} break;
case 'I':{test_pointer++; if(iRun) {runNextTest(); return;} else iRun=true; getIp(runNextTest);} break;
case 'D':{test_pointer++; if(dRun) {runNextTest(); return;} else dRun=true; testStatus=1; dlTest(runNextTest);} break;
case 'U':{test_pointer++; if(uRun) {runNextTest(); return;} else uRun=true; testStatus=3; ulTest(runNextTest);} break;
case 'P':{test_pointer++; if(pRun) {runNextTest(); return;} else pRun=true; testStatus=2; pingTest(runNextTest);} break;
case '_':{test_pointer++; setTimeout(runNextTest,1000);} break;
default: test_pointer++;
}
@ -221,6 +226,7 @@ function dlTest (done) {
interval = setInterval(function () {
tlog('DL: '+dlStatus+(graceTimeDone?'':' (in grace time)'))
var t = new Date().getTime() - startT
if (graceTimeDone) dlProgress = t / (settings.time_dl * 1000)
if (t < 200) return
if (!graceTimeDone){
if (t > 1000 * settings.time_dlGraceTime){
@ -232,11 +238,12 @@ function dlTest (done) {
}
}else{
var speed = totLoaded / (t / 1000.0)
dlStatus = ((speed * 8 * settings.overheadCompensationFactor)/1048576).toFixed(2) // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied, then everything is divided by 1048576 to go to megabits/s
dlStatus = ((speed * 8 * settings.overheadCompensationFactor)/(settings.useMebibits?1048576:1000000)).toFixed(2) // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied, then everything is divided by 1048576 or 1000000 to go to megabits/mebibits
if (((t / 1000.0) > settings.time_dl && dlStatus > 0) || failed) { // test is over, stop streams and timer
if (failed || isNaN(dlStatus)) dlStatus = 'Fail'
clearRequests()
clearInterval(interval)
dlProgress = 1
tlog('dlTest finished '+dlStatus)
done()
}
@ -337,6 +344,7 @@ function ulTest (done) {
interval = setInterval(function () {
tlog('UL: '+ulStatus+(graceTimeDone?'':' (in grace time)'))
var t = new Date().getTime() - startT
if (graceTimeDone) ulProgress = t / (settings.time_ul * 1000)
if (t < 200) return
if (!graceTimeDone){
if (t > 1000 * settings.time_ulGraceTime){
@ -348,11 +356,12 @@ function ulTest (done) {
}
}else{
var speed = totLoaded / (t / 1000.0)
ulStatus = ((speed * 8 * settings.overheadCompensationFactor)/1048576).toFixed(2) // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied, then everything is divided by 1048576 to go to megabits/s
ulStatus = ((speed * 8 * settings.overheadCompensationFactor)/(settings.useMebibits?1048576:1000000)).toFixed(2) // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied, then everything is divided by 1048576 or 1000000 to go to megabits/mebibits
if (((t / 1000.0) > settings.time_ul && ulStatus > 0) || failed) { // test is over, stop streams and timer
if (failed || isNaN(ulStatus)) ulStatus = 'Fail'
clearRequests()
clearInterval(interval)
ulProgress = 1
tlog('ulTest finished '+ulStatus)
done()
}
@ -373,6 +382,7 @@ function pingTest (done) {
// ping function
var doPing = function () {
tlog('ping')
pingProgress = i / settings.count_ping
prevT = new Date().getTime()
xhr[0] = new XMLHttpRequest()
xhr[0].onload = function () {
@ -381,7 +391,21 @@ function pingTest (done) {
if (i === 0) {
prevT = new Date().getTime() // first pong
} else {
var instspd = (new Date().getTime() - prevT)
var instspd = new Date().getTime() - prevT
if(settings.ping_allowPerformanceApi){
try{
//try to get accurate performance timing using performance api
var p=performance.getEntries()
p=p[p.length-1]
var d = p.responseStart - p.requestStart //best precision: chromium-based
if (d<=0) d=p.duration //edge: not so good precision because it also considers the overhead and there is no way to avoid it
if (d>0&&d<instspd) instspd=d
}catch(e){
//if not possible, keep the estimate
//firefox can't access performance api from worker: worst precision
tlog('Performance API not supported, using estimate')
}
}
var instjitter = Math.abs(instspd - prevInstspd)
if (i === 1) ping = instspd; /* first ping, can't tell jitter yet*/ else {
ping = ping * 0.9 + instspd * 0.1 // ping, weighted average
@ -393,7 +417,7 @@ function pingTest (done) {
jitterStatus = jitter.toFixed(2)
i++
tlog('PING: '+pingStatus+' JITTER: '+jitterStatus)
if (i < settings.count_ping) doPing(); else done() // more pings to do?
if (i < settings.count_ping) doPing(); else {pingProgress = 1; done()} // more pings to do?
}.bind(this)
xhr[0].onerror = function () {
// a ping failed, cancel test

File diff suppressed because one or more lines are too long