Calculate OpenWrt bandwidth between a specific timestamp

Wanted to see how much a bandwidth used between a specific timestamp? Curious about the size of a YouTube video or a System update? If you are the only one using your home router you can get an overall estimate of bandwidth usage using this quick script.

Notes

Needs a web server and PHP and you must have already configured your router for networkinfo.sh file. More info here>

Just create two php files and use index.php

index.php
<?php
$startTime = array_sum(explode(' ', microtime()));
header("Cache-Control: no-store, must-revalidate");
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Data Calculator</title>
<meta name="viewport" content="user-scalable=yes, initial-scale=1, width=device-width">
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
<link rel="stylesheet" type="text/css" href="/lib/css/dashboard-header.css">
<style>
/* Checkbox */
.box-inpt {
	position: absolute;
	width: 100px;
	height: 2em;
}
.autosave-checkbox {
	position: relative;
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
	display: block;
	opacity: 0;
	z-index: 1;
}
.autosave-checkbox:checked + .box-span-inpt .span-input {
	transform: translateX(80px);
}
.box-span-inpt {
	position: absolute;
	top: 0;
	left: 5px;
	width: 100%;
	height: 100%;
	border: 2px solid black;
	border-radius: 5px;
	overflow: hidden;
}
.span-input {
	position: absolute;
	top: 0;
	left: 0;
	width: 20px;
	height: 2em;
	background-color: black;
	transition: 0.3s;
}
.span-input::before, .span-input::after {
	position: absolute;
	top: 0;
	text-align: center;
	line-height: 2em;
	width: 80px;
	height: 100%;
	font-size: 1em;
	color: #ffffff;
	font-family: sans-serif;
}
.span-input::before {
	content: "ON";
	left: -80px;
	background-color: #00da00;
}
.span-input::after {
	content: "OFF";
	right: -80px;
	background-color: #ff002f;
}
</style>
</head>
<body>
<div class="header">
<span class="headerlogo">Current Data Calculator</span>
<input class="menu-btn" type="checkbox" id="menu-btn" />
<label class="menu-icon" for="menu-btn"><span class="navicon"></span></label>
<ul class="menu">
<li><a href="/">Home</a></li>
</ul>
</div>
<div class="content">
<div class="card">
<div class="primary-title">
<div class="primary-text">Bandwidth Monitoring</div>
</div>
<div class="supporting-text" style="font-size: 14px; line-height: 14px;">
<span style="line-height: 2.5em;"></span><span class="box-inpt"><input id="subscribeCheckbox" class="autosave-checkbox" type="checkbox" data-id="buzzer"><span class="box-span-inpt"><span class="span-input"></span></span></span>
<br><br><br>
<span class="totaldata"></span><br>
<span class="rxdata"></span><br>
<span class="txdata"></span>
</div>
<hr>
<div class="actions">
<div class="cardfooter"></div>
<div class="cardfooter float-right"><button id="clear-storage-btn">Clear All Data</button></div>
</div>
</div>

<div class="card">
<div class="primary-title">
<div class="primary-text">Probe router</div>
</div>
<div class="supporting-text" style="font-size: 14px; line-height: 14px;">
<button id="loadDataBtn">Probe router</button>
<div id="contentDisplay">Content will appear here...</div>
</div>
<hr>
<div class="actions">
<div class="cardfooter"></div>
<div class="cardfooter float-right"></div>
</div>
</div>
</div>
<script>
localStorage.clear();
document.getElementById("subscribeCheckbox").checked = false;
document.querySelector('.totaldata').innerHTML = "";
document.querySelector('.rxdata').innerHTML = "";
document.querySelector('.txdata').innerHTML = "";

// 1. Select the button and container elements
const button = document.getElementById('loadDataBtn');
const display = document.getElementById('contentDisplay');

// 2. Add the click event listener to the button
button.addEventListener('click', () => {
	// 3. Initiate the asynchronous network request
	fetch('router.php')
	.then(response => {
		if (!response.ok) {
			throw new Error('Network response failure');
		}
		return response.json(); // Or response.text() if plaintext
	})
	.then(data => {
		// 4. Update the DOM with the received data
		display.innerText = JSON.stringify(data);
	})
	.catch(error => {
		console.error('Error fetching data:', error);
		display.innerText = 'Failed to load data.';
	});
});

const checkbox = document.getElementById('subscribeCheckbox');

checkbox.addEventListener('change', (event) => {
    if (event.target.checked) {
	fetch('router.php')
	.then(response => {
		if (!response.ok) {
			throw new Error('Network response failure');
		}
		return response.json(); // Or response.text() if plaintext
	})
	.then(data => {
		// 4. Update the DOM with the received data
		localStorage.setItem('rxStart', data.rx);
		localStorage.setItem('txStart', data.tx);
		let rxStart = data.rx;
		let txStart = data.tx;
	})
	.catch(error => {
		console.error('Error fetching data:', error);
		display.innerText = 'Failed to load data.';
	});
    } else {
	fetch('router.php')
	.then(response => {
		if (!response.ok) {
			throw new Error('Network response failure');
		}
		return response.json(); // Or response.text() if plaintext
	})
	.then(data => {
		// 4. Update the DOM with the received data
		localStorage.setItem('rxStop', data.rx);
		localStorage.setItem('txStop', data.tx);
		rxStart = localStorage.getItem('rxStart');
		txStart = localStorage.getItem('txStart');
		let rxStop = localStorage.getItem('rxStop');
		let txStop = localStorage.getItem('txStop');
		let totalRx = rxStop - rxStart;
		let totalTx = txStop - txStart;
		let totalCombined = totalRx + totalTx;
		totalCombined = fileSizeSI(totalCombined);
		document.querySelector('.totaldata').innerHTML = "Total Data: <b>"+totalCombined+"</b>";
		totalRx = fileSizeSI(totalRx);
		document.querySelector('.rxdata').innerHTML = "Rx: <b>"+totalRx+"</b>";
		totalTx = fileSizeSI(totalTx);
		document.querySelector('.txdata').innerHTML = "Tx: <b>"+totalTx+"</b>";
	})
	.catch(error => {
		console.error('Error fetching data:', error);
	});
    }
});

// 1. Select the button element
const clearBtn = document.getElementById('clear-storage-btn');
// 2. Add a click event listener
clearBtn.addEventListener('click', () => {
// 3. Clear all localStorage for the current domain
localStorage.clear();
document.getElementById("subscribeCheckbox").checked = false;
document.querySelector('.totaldata').innerHTML = "";
document.querySelector('.rxdata').innerHTML = "";
document.querySelector('.txdata').innerHTML = "";
// 4. (Optional) Refresh the page or update the UI to reflect changes
//location.reload();
});

function fileSizeSI(bytes) {
	const exponent = Math.floor(Math.log(bytes) / Math.log(1000.0));
	const decimal = (bytes / Math.pow(1000.0, exponent)).toFixed(exponent ? 2 : 0);
		if (bytes <= 0) {
		return "0 Bytes";
	}
	return `${decimal} ${exponent ? `${'kMGTPEZY'[exponent - 1]}B` : 'B'}`;
}
var number_of_elements = document.getElementsByClassName('siunits').length;
var i=0;
while (i<number_of_elements) {
var sivalue = document.getElementsByClassName("siunits")[i].innerText;
sivalue = fileSizeSI(sivalue);
document.getElementsByClassName('siunits')[i].textContent = "("+sivalue+")";
i++;
}
</script>
</body>
</html>

Router.php file, change the IP address of your router.

router.php
<?php
// Set headers to return JSON response
header('Content-Type: application/json');
$url = 'http://192.168.1.1/cgi-bin/networkinfo.sh';

$json_data = file_get_contents($url, 0, stream_context_create(["http"=>["timeout"=>15]]));
$data_array = json_decode($json_data, true);
if ($data_array === null && json_last_error() !== JSON_ERROR_NONE) {
	echo "Error decoding JSON: " . json_last_error_msg();
	$response = ["rx" => "No data", "tx" => "No data"];
	exit;
} else {
	$rx = $data_array['rx_bytes'];
	$tx = $data_array['tx_bytes'];
	$response = ["rx" => $rx, "tx" => $tx];
}
echo json_encode($response);
?>

Screenshot

OpenWrt Timestamp bandwidth Screenshot

Made for local self hosting only, not for public Internet!

Let me know if you have any comments or if there is any error in this guide.