Speedtest worker now outputs status as JSON for easier parsing; Removed partial CSV implementation; Updated examples and documentation
This commit is contained in:
parent
0ce73a7e6c
commit
0954c6a6ac
62
doc.md
62
doc.md
|
@ -1,7 +1,7 @@
|
||||||
# HTML5 Speedtest
|
# HTML5 Speedtest
|
||||||
|
|
||||||
> by Federico Dossena
|
> by Federico Dossena
|
||||||
> Version 4.6, August 7, 2018
|
> Version 4.6.1, August 8, 2018
|
||||||
> [https://github.com/adolfintel/speedtest/](https://github.com/adolfintel/speedtest/)
|
> [https://github.com/adolfintel/speedtest/](https://github.com/adolfintel/speedtest/)
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,18 +107,8 @@ we'll see the details of the format of the response.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
w.onmessage = function (event) {
|
w.onmessage = function (event) {
|
||||||
var data = event.data.split(';')
|
var data = JSON.parse(event.data);
|
||||||
var testState = data[0]
|
if (data.testState >= 4) {
|
||||||
var dlStatus = data[1]
|
|
||||||
var ulStatus = data[2]
|
|
||||||
var pingStatus = data[3]
|
|
||||||
var jitterStatus = data[5]
|
|
||||||
var clientIp = data[4]
|
|
||||||
var dlProgress = data[6]
|
|
||||||
var ulProgress = data[7]
|
|
||||||
var pingProgress = data[8]
|
|
||||||
var testId = data[9]
|
|
||||||
if (testState >= 4) {
|
|
||||||
clearInterval(timer) // test is finished or aborted
|
clearInterval(timer) // test is finished or aborted
|
||||||
}
|
}
|
||||||
// .. update your page here ..
|
// .. update your page here ..
|
||||||
|
@ -126,12 +116,9 @@ w.onmessage = function (event) {
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Response format
|
#### Response format
|
||||||
The response from the worker is composed of values separated by `;` (semicolon) in this
|
The response from the worker is a JSON string containing these entries:
|
||||||
format:
|
|
||||||
|
|
||||||
`testState;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus;dlProgress;ulProgress;pingProgress`
|
* __testState__: an integer between -1 and 5
|
||||||
|
|
||||||
* __testState__ is an integer between -1 and 5
|
|
||||||
* `-1` = Test not started yet
|
* `-1` = Test not started yet
|
||||||
* `0` = Test starting
|
* `0` = Test starting
|
||||||
* `1` = Download test in progress
|
* `1` = Download test in progress
|
||||||
|
@ -139,22 +126,22 @@ format:
|
||||||
* `3` = Upload test in progress
|
* `3` = Upload test in progress
|
||||||
* `4` = Test finished
|
* `4` = Test finished
|
||||||
* `5` = Test aborted
|
* `5` = Test aborted
|
||||||
* __dlStatus__ is either
|
* __dlStatus__: either
|
||||||
* Empty string (not started or aborted)
|
* Empty string (not started or aborted)
|
||||||
* Download speed in Megabit/s as a number with 2 decimals
|
* Download speed in Megabit/s as a number with 2 decimals
|
||||||
* The string "Fail" (test failed)
|
* The string "Fail" (test failed)
|
||||||
* __ulStatus__ is either
|
* __ulStatus__: either
|
||||||
* Empty string (not started or aborted)
|
* Empty string (not started or aborted)
|
||||||
* Upload speed in Megabit/s as a number with 2 decimals
|
* Upload speed in Megabit/s as a number with 2 decimals
|
||||||
* The string "Fail" (test failed)
|
* The string "Fail" (test failed)
|
||||||
* __pingStatus__ is either
|
* __pingStatus__: either
|
||||||
* Empty string (not started or aborted)
|
* Empty string (not started or aborted)
|
||||||
* Estimated ping in milliseconds as a number with 2 decimals
|
* Estimated ping in milliseconds as a number with 2 decimals
|
||||||
* The string "Fail" (test failed)
|
* The string "Fail" (test failed)
|
||||||
* __clientIp__ is either
|
* __clientIp__: either
|
||||||
* Empty string (not fetched yet or failed)
|
* Empty string (not fetched yet or failed)
|
||||||
* The client's IP address as a string
|
* The client's IP address as a string (with ISP info if enabled)
|
||||||
* __jitterStatus__ is either
|
* __jitterStatus__: either
|
||||||
* Empty string (not started or aborted)
|
* Empty string (not started or aborted)
|
||||||
* Estimated jitter in milliseconds as a number with 2 decimals (lower = stable connection)
|
* Estimated jitter in milliseconds as a number with 2 decimals (lower = stable connection)
|
||||||
* The string "Fail" (test failed)
|
* The string "Fail" (test failed)
|
||||||
|
@ -278,7 +265,11 @@ w.postMessage('start '+JSON.stringify(params))
|
||||||
* `1514 / 1460`: TCP+IPv4+ETH, ignoring HTTP overhead
|
* `1514 / 1460`: TCP+IPv4+ETH, ignoring HTTP overhead
|
||||||
* `1514 / 1440`: TCP+IPv6+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
|
* `1`: ignore overheads. This measures the speed at which you actually download and upload files rather than the raw connection speed
|
||||||
* __telemetry_extra__: Extra data that you want to be passed to the telemetry. This is a string field, if you want to pass an object, make sure you use ``JSON.stringify``.
|
* __telemetry_level__: The type of telemetry to use. See the telemetry section for more info about this
|
||||||
|
* Default: `none`
|
||||||
|
* `basic`: send results only
|
||||||
|
* `full`: send results and debug info
|
||||||
|
* __telemetry_extra__: Extra data that you want to be passed to the telemetry. This is a string field, if you want to pass an object, make sure you use ``JSON.stringify``. This string will be added to the database entry for this test.
|
||||||
|
|
||||||
### Aborting the test prematurely
|
### Aborting the test prematurely
|
||||||
The test can be aborted at any time by sending an abort command to the worker:
|
The test can be aborted at any time by sending an abort command to the worker:
|
||||||
|
@ -327,10 +318,10 @@ You need to start the test with your replacements like this:
|
||||||
w.postMessage('start {"url_dl": "newGarbageURL", "url_ul": "newEmptyURL", "url_ping": "newEmptyURL", "url_getIp": "newIpURL"}')
|
w.postMessage('start {"url_dl": "newGarbageURL", "url_ul": "newEmptyURL", "url_ping": "newEmptyURL", "url_getIp": "newIpURL"}')
|
||||||
```
|
```
|
||||||
## Telemetry
|
## Telemetry
|
||||||
Telemetry currently requires PHP and either MySQL, PostgreSQL or SQLite. Alternatively, it is possible to save to a CSV file.
|
Telemetry currently requires PHP and either MySQL, PostgreSQL or SQLite.
|
||||||
To set up the telemetry, we need to do 4 things:
|
To set up the telemetry, we need to do 4 things:
|
||||||
* copy the `telemetry` folder
|
* copy the `telemetry` folder
|
||||||
* edit `telemetry_settings.php` to add your database or CSV settings
|
* edit `telemetry_settings.php` to add your database settings
|
||||||
* create the database
|
* create the database
|
||||||
* enable telemetry
|
* enable telemetry
|
||||||
|
|
||||||
|
@ -341,7 +332,7 @@ If you see a table called `speedtest_users`, empty, you did it right.
|
||||||
|
|
||||||
### Configuring `telemetry.php`
|
### Configuring `telemetry.php`
|
||||||
Open `telemetry_settings.php` with notepad or a similar text editor.
|
Open `telemetry_settings.php` with notepad or a similar text editor.
|
||||||
Set your preferred database, ``$db_type="mysql";``, ``$db_type="sqlite";``, ``$db_type="postgresql";`` or ``$db_type="csv";``
|
Set your preferred database, ``$db_type="mysql";``, ``$db_type="sqlite";`` or ``$db_type="postgresql";``
|
||||||
If you choose to use Sqlite3, you must set the path to your database file:
|
If you choose to use Sqlite3, you must set the path to your database file:
|
||||||
```php
|
```php
|
||||||
$Sqlite_db_file = "../telemetry.sql";
|
$Sqlite_db_file = "../telemetry.sql";
|
||||||
|
@ -363,26 +354,19 @@ $PostgreSql_hostname="DB_HOSTNAME"; //database address, usually localhost
|
||||||
$PostgreSql_databasename="DB_NAME"; //the name of the database where you loaded telemetry_postgresql.sql
|
$PostgreSql_databasename="DB_NAME"; //the name of the database where you loaded telemetry_postgresql.sql
|
||||||
```
|
```
|
||||||
|
|
||||||
If you choose to use a CSV file, you must set the Csv_File and timezone variables.
|
|
||||||
```php
|
|
||||||
$Csv_File="myReportFile.csv";
|
|
||||||
$timezone='Europe/Paris';
|
|
||||||
```
|
|
||||||
__Note__: CSV currently only supports basic telemetry, the log will not be saved
|
|
||||||
|
|
||||||
### Enabling telemetry
|
### Enabling telemetry
|
||||||
Edit your test page; where you start the worker, you need to specify the `telemetry_level`.
|
Edit your test page; where you start the worker, you need to specify the `telemetry_level`.
|
||||||
There are 3 levels:
|
There are 3 levels:
|
||||||
* `none`: telemetry is disabled (default)
|
* `none`: telemetry is disabled (default)
|
||||||
* `basic`: telemetry collects IP, ISP info, User Agent, Preferred language, Test results
|
* `basic`: telemetry collects IP, ISP info, User Agent, Preferred language, Test results
|
||||||
* `full`: same as above, but also collects a log (10-150 Kb each, not recommended)
|
* `full`: same as above, but also collects a debug log (10-150 Kb each, not recommended unless you're developing the speedtest)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```js
|
```js
|
||||||
w.postMessage('start {"telemetry_level":"basic"}')
|
w.postMessage('start {"telemetry_level":"basic"}')
|
||||||
```
|
```
|
||||||
|
|
||||||
Also, see example-telemetry.html
|
You can use example-telemetryEnabled.html and example-telemetry-resultSharing.html as starting points.
|
||||||
|
|
||||||
### Results sharing
|
### Results sharing
|
||||||
This feature generates an image that can be share by the user containing the download, upload, ping, jitter and ISP (if enabled).
|
This feature generates an image that can be share by the user containing the download, upload, ping, jitter and ISP (if enabled).
|
||||||
|
@ -391,8 +375,6 @@ To use this feature, copy the `results` folder. You can customize the style of t
|
||||||
|
|
||||||
This feature requires Telemetry to be enabled, and FreeType2 must be installed in PHP (if not already be installed by your distro).
|
This feature requires Telemetry to be enabled, and FreeType2 must be installed in PHP (if not already be installed by your distro).
|
||||||
|
|
||||||
__Note:__ CSV doesn't currently support this.
|
|
||||||
|
|
||||||
__Important:__ This feature relies on PHP functions `imagefttext` and `imageftbbox` that are well known for being problematic. The most common problem is that they can't find the font files and therefore nothing is drawn. This problem is metioned [here](http://php.net/manual/en/function.imagefttext.php) and was experienced by a lot of users.
|
__Important:__ This feature relies on PHP functions `imagefttext` and `imageftbbox` that are well known for being problematic. The most common problem is that they can't find the font files and therefore nothing is drawn. This problem is metioned [here](http://php.net/manual/en/function.imagefttext.php) and was experienced by a lot of users.
|
||||||
|
|
||||||
### Seeing the results
|
### Seeing the results
|
||||||
|
@ -400,8 +382,6 @@ A basic front-end for visualizing and searching tests by ID is available in `tel
|
||||||
|
|
||||||
A login is required to access the interface. __Important__: change the default password in `telemetry_settings.php`.
|
A login is required to access the interface. __Important__: change the default password in `telemetry_settings.php`.
|
||||||
|
|
||||||
__Note:__ CSV doesn't currently support this.
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
These are the most common issues reported by users, and how to fix them. If you still need help, contact me at [info@fdossena.com](mailto:info@fdossena.com).
|
These are the most common issues reported by users, and how to fix them. If you still need help, contact me at [info@fdossena.com](mailto:info@fdossena.com).
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,11 @@
|
||||||
var w = new Worker('speedtest_worker.min.js') // create new worker
|
var w = new Worker('speedtest_worker.min.js') // create new worker
|
||||||
setInterval(function () { w.postMessage('status') }, 100) // ask for status every 100ms
|
setInterval(function () { w.postMessage('status') }, 100) // ask for status every 100ms
|
||||||
w.onmessage = function (event) { // when status is received, split the string and put the values in the appropriate fields
|
w.onmessage = function (event) { // when status is received, split the string and put the values in the appropriate fields
|
||||||
var data = event.data.split(';') // string format: status;download;upload;ping (speeds are in mbit/s) (status: 0=not started, 1=downloading, 2=uploading, 3=ping, 4=done, 5=aborted)
|
var data = JSON.parse(event.data); //fetch speedtest worker output
|
||||||
document.getElementById('download').textContent = data[1] + ' Mbit/s'
|
document.getElementById('download').textContent = data.dlStatus + ' Mbit/s'
|
||||||
document.getElementById('upload').textContent = data[2] + ' Mbit/s'
|
document.getElementById('upload').textContent = data.ulStatus + ' Mbit/s'
|
||||||
document.getElementById('ping').textContent = data[3] + ' ms, ' + data[5] + ' ms jitter'
|
document.getElementById('ping').textContent = data.pingStatus + ' ms, ' + data.jitterStatus + ' ms jitter'
|
||||||
document.getElementById('ip').textContent = data[4]
|
document.getElementById('ip').textContent = data.clientIp
|
||||||
}
|
}
|
||||||
w.postMessage('start') // start the speedtest (default params. keep garbage.php and empty.dat in the same directory as the js file)
|
w.postMessage('start') // start the speedtest (default params. keep garbage.php and empty.dat in the same directory as the js file)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -200,8 +200,8 @@
|
||||||
w = new Worker('speedtest_worker.min.js')
|
w = new Worker('speedtest_worker.min.js')
|
||||||
var interval = setInterval(function () { w.postMessage('status') }, 100)
|
var interval = setInterval(function () { w.postMessage('status') }, 100)
|
||||||
w.onmessage = function (event) {
|
w.onmessage = function (event) {
|
||||||
var data = event.data.split(';')
|
var data = JSON.parse(event.data)
|
||||||
var status = Number(data[0])
|
var status = data.testStatus
|
||||||
if (status >= 4) {
|
if (status >= 4) {
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
document.getElementById('abortBtn').style.display = 'none'
|
document.getElementById('abortBtn').style.display = 'none'
|
||||||
|
@ -211,24 +211,24 @@
|
||||||
if (status === 5) {
|
if (status === 5) {
|
||||||
document.getElementById('testArea').style.display = 'none'
|
document.getElementById('testArea').style.display = 'none'
|
||||||
}
|
}
|
||||||
if (status === 1 && Number(data[1]) > 0) {
|
if (status === 1 && Number(data.dlStatus) > 0) {
|
||||||
chart1.data.datasets[0].data[~~(20*Number(data[6]))]=(Number(data[1]))
|
chart1.data.datasets[0].data[~~(20*Number(data.dlProgress))]=(Number(data.dlStatus))
|
||||||
chart1.data.labels[chart1.data.datasets[0].data.length - 1] = ''
|
chart1.data.labels[chart1.data.datasets[0].data.length - 1] = ''
|
||||||
chart1.update()
|
chart1.update()
|
||||||
}
|
}
|
||||||
if (status === 3 && Number(data[2]) > 0) {
|
if (status === 3 && Number(data.ulStatus) > 0) {
|
||||||
chart1.data.datasets[1].data[~~(20*Number(data[7]))]=(Number(data[2]))
|
chart1.data.datasets[1].data[~~(20*Number(data.ulProgress))]=(Number(data.ulStatus))
|
||||||
chart1.data.labels[chart1.data.datasets[1].data.length - 1] = ''
|
chart1.data.labels[chart1.data.datasets[1].data.length - 1] = ''
|
||||||
chart1.update()
|
chart1.update()
|
||||||
}
|
}
|
||||||
if (status === 2 && Number(data[3]) > 0) {
|
if (status === 2 && Number(data.pingStatus) > 0) {
|
||||||
chart2.data.datasets[0].data.push(Number(data[3]))
|
chart2.data.datasets[0].data.push(Number(data.pingStatus))
|
||||||
chart2.data.datasets[1].data.push(Number(data[5]))
|
chart2.data.datasets[1].data.push(Number(data.jitterStatus))
|
||||||
chart2.data.labels[chart2.data.datasets[0].data.length - 1] = ''
|
chart2.data.labels[chart2.data.datasets[0].data.length - 1] = ''
|
||||||
chart2.data.labels[chart2.data.datasets[1].data.length - 1] = ''
|
chart2.data.labels[chart2.data.datasets[1].data.length - 1] = ''
|
||||||
chart2.update()
|
chart2.update()
|
||||||
}
|
}
|
||||||
ip.textContent = data[4]
|
ip.textContent = data.clientIp
|
||||||
}
|
}
|
||||||
w.postMessage('start')
|
w.postMessage('start')
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,18 +131,18 @@ function startStop(){
|
||||||
w.postMessage('start '+JSON.stringify(parameters)); //run the test with custom parameters
|
w.postMessage('start '+JSON.stringify(parameters)); //run the test with custom parameters
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
var data=e.data.split(';');
|
var data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
w=null;
|
w=null;
|
||||||
}
|
}
|
||||||
I("ip").textContent=data[4];
|
I("ip").textContent=data.clientIp;
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
I("pingText").textContent=data[3];
|
I("pingText").textContent=data.pingStatus;
|
||||||
I("jitText").textContent=data[5];
|
I("jitText").textContent=data.jitterStatus;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,15 +125,15 @@ function startStop(){
|
||||||
w.postMessage('start {"test_order":"D_U"}'); //run only download and upload tests, with a 1s pause in between
|
w.postMessage('start {"test_order":"D_U"}'); //run only download and upload tests, with a 1s pause in between
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
var data=e.data.split(';');
|
var data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
w=null;
|
w=null;
|
||||||
}
|
}
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,8 +163,8 @@ function startStop(){
|
||||||
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
data=e.data.split(';');
|
data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
|
@ -177,16 +177,16 @@ function startStop(){
|
||||||
//this function reads the data sent back by the worker and updates the UI
|
//this function reads the data sent back by the worker and updates the UI
|
||||||
function updateUI(forced){
|
function updateUI(forced){
|
||||||
if(!forced&&(!data||!w)) return;
|
if(!forced&&(!data||!w)) return;
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
I("ip").textContent=data[4];
|
I("ip").textContent=data.clientIp;
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
drawMeter(I("dlMeter"),mbpsToAmount(Number(data[1]*(status==1?oscillate():1))),meterBk,dlColor,Number(data[6]),progColor);
|
drawMeter(I("dlMeter"),mbpsToAmount(Number(data.dlStatus*(status==1?oscillate():1))),meterBk,dlColor,Number(data.dlProgress),progColor);
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
drawMeter(I("ulMeter"),mbpsToAmount(Number(data[2]*(status==3?oscillate():1))),meterBk,ulColor,Number(data[7]),progColor);
|
drawMeter(I("ulMeter"),mbpsToAmount(Number(data.ulStatus*(status==3?oscillate():1))),meterBk,ulColor,Number(data.ulProgress),progColor);
|
||||||
I("pingText").textContent=data[3];
|
I("pingText").textContent=data.pingStatus;
|
||||||
drawMeter(I("pingMeter"),msToAmount(Number(data[3]*(status==2?oscillate():1))),meterBk,pingColor,Number(data[8]),progColor);
|
drawMeter(I("pingMeter"),msToAmount(Number(data.pingStatus*(status==2?oscillate():1))),meterBk,pingColor,Number(data.pingProgress),progColor);
|
||||||
I("jitText").textContent=data[5];
|
I("jitText").textContent=data.jitterStatus;
|
||||||
drawMeter(I("jitMeter"),msToAmount(Number(data[5]*(status==2?oscillate():1))),meterBk,jitColor,Number(data[8]),progColor);
|
drawMeter(I("jitMeter"),msToAmount(Number(data.jitterStatus*(status==2?oscillate():1))),meterBk,jitColor,Number(data.pingProgress),progColor);
|
||||||
}
|
}
|
||||||
function oscillate(){
|
function oscillate(){
|
||||||
return 1+0.02*Math.sin(Date.now()/100);
|
return 1+0.02*Math.sin(Date.now()/100);
|
||||||
|
|
|
@ -125,18 +125,18 @@ function startStop(){
|
||||||
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
var data=e.data.split(';');
|
var data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
w=null;
|
w=null;
|
||||||
}
|
}
|
||||||
I("ip").textContent=data[4];
|
I("ip").textContent=data.clientIp;
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
I("pingText").textContent=data[3];
|
I("pingText").textContent=data.pingStatus;
|
||||||
I("jitText").textContent=data[5];
|
I("jitText").textContent=data.jitterStatus;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,19 +143,19 @@ function startStop(){
|
||||||
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
var data=e.data.split(';');
|
var data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
w=null;
|
w=null;
|
||||||
}
|
}
|
||||||
I("ip").textContent=data[4];
|
I("ip").textContent=data.clientIp;
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
I("pingText").textContent=data[3];
|
I("pingText").textContent=data.pingStatus;
|
||||||
I("jitText").textContent=data[5];
|
I("jitText").textContent=data.jitterStatus;
|
||||||
var prog=(Number(data[6])*2+Number(data[7])*2+Number(data[8]))/5;
|
var prog=(Number(data.dlProgress)*2+Number(data.ulProgress)*2+Number(data.pingProgress))/5;
|
||||||
I("progress").style.width=(100*prog)+"%";
|
I("progress").style.width=(100*prog)+"%";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,8 @@ function startStop(){
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
I("shareArea").style.display="none";
|
I("shareArea").style.display="none";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
data=e.data.split(';');
|
data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
|
@ -190,7 +190,7 @@ function startStop(){
|
||||||
if(status==4){
|
if(status==4){
|
||||||
//if testId is present, show sharing panel, otherwise do nothing
|
//if testId is present, show sharing panel, otherwise do nothing
|
||||||
try{
|
try{
|
||||||
var testId=Number(data[9]);
|
var testId=Number(data.testId);
|
||||||
if(!isNaN(testId)){
|
if(!isNaN(testId)){
|
||||||
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
|
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
|
||||||
I("resultsImg").src=shareURL;
|
I("resultsImg").src=shareURL;
|
||||||
|
@ -207,16 +207,16 @@ function startStop(){
|
||||||
//this function reads the data sent back by the worker and updates the UI
|
//this function reads the data sent back by the worker and updates the UI
|
||||||
function updateUI(forced){
|
function updateUI(forced){
|
||||||
if(!forced&&(!data||!w)) return;
|
if(!forced&&(!data||!w)) return;
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus;
|
||||||
I("ip").textContent=data[4];
|
I("ip").textContent=data.clientIp;
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
drawMeter(I("dlMeter"),mbpsToAmount(Number(data[1]*(status==1?oscillate():1))),meterBk,dlColor,Number(data[6]),progColor);
|
drawMeter(I("dlMeter"),mbpsToAmount(Number(data.dlStatus*(status==1?oscillate():1))),meterBk,dlColor,Number(data.dlProgress),progColor);
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
drawMeter(I("ulMeter"),mbpsToAmount(Number(data[2]*(status==3?oscillate():1))),meterBk,ulColor,Number(data[7]),progColor);
|
drawMeter(I("ulMeter"),mbpsToAmount(Number(data.ulStatus*(status==3?oscillate():1))),meterBk,ulColor,Number(data.ulProgress),progColor);
|
||||||
I("pingText").textContent=data[3];
|
I("pingText").textContent=data.pingStatus;
|
||||||
drawMeter(I("pingMeter"),msToAmount(Number(data[3]*(status==2?oscillate():1))),meterBk,pingColor,Number(data[8]),progColor);
|
drawMeter(I("pingMeter"),msToAmount(Number(data.pingStatus*(status==2?oscillate():1))),meterBk,pingColor,Number(data.pingProgress),progColor);
|
||||||
I("jitText").textContent=data[5];
|
I("jitText").textContent=data.jitterStatus;
|
||||||
drawMeter(I("jitMeter"),msToAmount(Number(data[5]*(status==2?oscillate():1))),meterBk,jitColor,Number(data[8]),progColor);
|
drawMeter(I("jitMeter"),msToAmount(Number(data.jitterStatus*(status==2?oscillate():1))),meterBk,jitColor,Number(data.pingProgress),progColor);
|
||||||
}
|
}
|
||||||
function oscillate(){
|
function oscillate(){
|
||||||
return 1+0.02*Math.sin(Date.now()/100);
|
return 1+0.02*Math.sin(Date.now()/100);
|
||||||
|
|
|
@ -125,18 +125,18 @@ function startStop(){
|
||||||
w.postMessage('start {"telemetry_level":"basic"}'); //Add optional parameters (see doc.md)
|
w.postMessage('start {"telemetry_level":"basic"}'); //Add optional parameters (see doc.md)
|
||||||
I("startStopBtn").className="running";
|
I("startStopBtn").className="running";
|
||||||
w.onmessage=function(e){
|
w.onmessage=function(e){
|
||||||
var data=e.data.split(';');
|
var data=JSON.parse(e.data);
|
||||||
var status=Number(data[0]);
|
var status=data.testStatus
|
||||||
if(status>=4){
|
if(status>=4){
|
||||||
//test completed
|
//test completed
|
||||||
I("startStopBtn").className="";
|
I("startStopBtn").className="";
|
||||||
w=null;
|
w=null;
|
||||||
}
|
}
|
||||||
I("ip").textContent=data[4];
|
I("ip").textContent=data.clientIp;
|
||||||
I("dlText").textContent=(status==1&&data[1]==0)?"...":data[1];
|
I("dlText").textContent=(status==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||||
I("ulText").textContent=(status==3&&data[2]==0)?"...":data[2];
|
I("ulText").textContent=(status==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||||
I("pingText").textContent=data[3];
|
I("pingText").textContent=data.pingStatus;
|
||||||
I("jitText").textContent=data[5];
|
I("jitText").textContent=data.jitterStatus;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
HTML5 Speedtest v4.6
|
HTML5 Speedtest v4.6.1
|
||||||
by Federico Dossena
|
by Federico Dossena
|
||||||
https://github.com/adolfintel/speedtest/
|
https://github.com/adolfintel/speedtest/
|
||||||
GNU LGPLv3 License
|
GNU LGPLv3 License
|
||||||
|
@ -63,7 +63,7 @@ function url_sep (url) { return url.match(/\?/) ? '&' : '?'; }
|
||||||
/*
|
/*
|
||||||
listener for commands from main thread to this worker.
|
listener for commands from main thread to this worker.
|
||||||
commands:
|
commands:
|
||||||
-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
|
-status: returns the current status as a JSON string containing testStatus, dlStatus, ulStatus, pingStatus, clientIp, jitterStatus, dlProgress, ulProgress, pingProgress
|
||||||
-abort: aborts the current test
|
-abort: aborts the current test
|
||||||
-start: starts the test. optionally, settings can be passed as JSON.
|
-start: starts the test. optionally, settings can be passed as JSON.
|
||||||
example: start {"time_ul":"10", "time_dl":"10", "count_ping":"50"}
|
example: start {"time_ul":"10", "time_dl":"10", "count_ping":"50"}
|
||||||
|
@ -71,7 +71,18 @@ function url_sep (url) { return url.match(/\?/) ? '&' : '?'; }
|
||||||
this.addEventListener('message', function (e) {
|
this.addEventListener('message', function (e) {
|
||||||
var params = e.data.split(' ')
|
var params = e.data.split(' ')
|
||||||
if (params[0] === 'status') { // return status
|
if (params[0] === 'status') { // return status
|
||||||
postMessage(testStatus + ';' + dlStatus + ';' + ulStatus + ';' + pingStatus + ';' + clientIp + ';' + jitterStatus + ';' + dlProgress + ';' + ulProgress + ';' + pingProgress+ ';' + testId)
|
postMessage(JSON.stringify({
|
||||||
|
testStatus:testStatus,
|
||||||
|
dlStatus:dlStatus,
|
||||||
|
ulStatus:ulStatus,
|
||||||
|
pingStatus:pingStatus,
|
||||||
|
clientIp:clientIp,
|
||||||
|
jitterStatus:jitterStatus,
|
||||||
|
dlProgress:dlProgress,
|
||||||
|
ulProgress:ulProgress,
|
||||||
|
pingProgress:pingProgress,
|
||||||
|
testId:testId
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
if (params[0] === 'start' && testStatus === -1) { // start new test
|
if (params[0] === 'start' && testStatus === -1) { // start new test
|
||||||
testStatus = 0
|
testStatus = 0
|
||||||
|
|
2
speedtest_worker.min.js
vendored
2
speedtest_worker.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -56,26 +56,5 @@ if($db_type=="mysql"){
|
||||||
echo "id ".$conn->lastInsertId();
|
echo "id ".$conn->lastInsertId();
|
||||||
$conn = null;
|
$conn = null;
|
||||||
}
|
}
|
||||||
elseif($db_type=="csv"){
|
else die("-1");
|
||||||
// Prepare the csv formatted string
|
|
||||||
date_default_timezone_set($timezone);
|
|
||||||
$date = date('Y-m-d H:i:s');
|
|
||||||
$str = '"' . $date . '",';
|
|
||||||
$str .= '"' . $ip . '",';
|
|
||||||
$str .= '"' . $ispinfo . '",';
|
|
||||||
$str .= '"' . $ua . '",';
|
|
||||||
$str .= '"' . $dl . '",';
|
|
||||||
$str .= '"' . $ul . '",';
|
|
||||||
$str .= '"' . $ping . '",';
|
|
||||||
$str .= '"' . $jitter . '"' . "\n";
|
|
||||||
|
|
||||||
// Set header if this is a new file
|
|
||||||
if (!file_exists($Csv_File)) {
|
|
||||||
$header = '"date","ip","ispinfo","ua","download","upload","ping","jitter"' . "\n";
|
|
||||||
file_put_contents($Csv_File, $header, FILE_APPEND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write line to file
|
|
||||||
file_put_contents($Csv_File, $str, FILE_APPEND);
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$db_type="mysql"; //Type of db: "mysql", "sqlite", "postgresql" or "csv"
|
$db_type="mysql"; //Type of db: "mysql", "sqlite" or "postgresql"
|
||||||
$stats_password="PASSWORD"; //password to login to stats.php. Change this!!!
|
$stats_password="PASSWORD"; //password to login to stats.php. Change this!!!
|
||||||
|
|
||||||
// Sqlite3 settings
|
// Sqlite3 settings
|
||||||
|
@ -18,11 +18,6 @@ $PostgreSql_password="PASSWORD";
|
||||||
$PostgreSql_hostname="DB_HOSTNAME";
|
$PostgreSql_hostname="DB_HOSTNAME";
|
||||||
$PostgreSql_databasename="DB_NAME";
|
$PostgreSql_databasename="DB_NAME";
|
||||||
|
|
||||||
// CSV settings
|
|
||||||
$Csv_File="../../reports.csv";
|
|
||||||
$timezone='UTC';
|
|
||||||
|
|
||||||
|
//IMPORTANT: DO NOT ADD ANYTHING BELOW THIS PHP CLOSING TAG, NOT EVEN EMPTY LINES!
|
||||||
|
|
||||||
//IMPORTANT: DO NOT ADD ANYTHING BELOW THIS PHP CLOSING TAGS, NOT EVEN EMPTY LINES!
|
|
||||||
?>
|
?>
|
Loading…
Reference in a new issue