Skip to content

Commit 8d7710a

Browse files
authored
Merge pull request #1 from ajxv/develop
Develop
2 parents 64dc3af + 44106ab commit 8d7710a

File tree

5 files changed

+266
-106
lines changed

5 files changed

+266
-106
lines changed

README.md

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,119 @@
1-
# netspeed-monitor
1+
# Network Speed Monitor
22

3-
This Gnome extension displays the current network speed in the top bar of Ubuntu.
3+
Network Speed Monitor is a GNOME extension that displays the current network speed on the top bar of your Ubuntu desktop. It provides a real-time view of your download and upload speeds, helping you monitor your network usage efficiently.
4+
5+
## Features
6+
7+
- Real-time network speed monitoring
8+
- Easy-to-read display on the top bar
9+
- Customizable refresh interval
10+
- Supports multiple network interfaces
411

512
## Installation
613

14+
To install the Network Speed Monitor extension:
15+
16+
1. **Download the extension:**
17+
- Clone the repository to your local machine:
18+
```sh
19+
git clone https://github.com/ajxv/netspeed-monitor.git
20+
```
21+
22+
2. **Install the extension:**
23+
- Copy the extension files to the GNOME extensions directory:
24+
```sh
25+
cp -r netspeed-monitor ~/.local/share/gnome-shell/extensions/netspeed-monitor@ajxv/
26+
```
27+
28+
3. **Enable the extension:**
29+
- Open GNOME Tweaks and navigate to the Extensions tab, then enable the Network Speed Monitor extension.
30+
- Alternatively, you can enable the extension using the command line:
31+
```sh
32+
gnome-extensions enable netspeed-monitor@ajxv
33+
```
34+
35+
4. **Restart GNOME Shell:**
36+
- Press `Alt + F2`, type `r`, and press `Enter` to restart GNOME Shell.
737

838
## Usage
939

10-
After installing and enabling the extension, the current network speed will be displayed in the top bar of Ubuntu. The speed is updated every few seconds.
40+
Once installed and enabled, the Network Speed Monitor extension will display the current download (↓) and upload (↑) speeds on the top bar of your Ubuntu desktop. The speeds are updated every few seconds based on the configured refresh interval.
41+
42+
## ScreenShot
43+
![alt text](screenshots/screenshot1.png)
44+
45+
## Technical Details: Network Speed Calculations
46+
47+
### Data Source
48+
The extension reads network statistics from `/proc/net/dev`, a Linux kernel interface that provides cumulative network traffic statistics. This file contains rows for each network interface with various counters including bytes received (RX) and transmitted (TX).
49+
50+
### Speed Calculation Process
51+
1. **Data Collection**
52+
- The system reads `/proc/net/dev` every 3 seconds
53+
- Interface statistics are aggregated, excluding virtual interfaces (lo, vir, vbox, docker, br-)
54+
- Two primary values are tracked:
55+
- Total bytes received (RX)
56+
- Total bytes transmitted (TX)
57+
58+
2. **Speed Calculation Formula**
59+
```sh
60+
- Speed = (Current Bytes - Previous Bytes) / Interval Time
61+
- RX Speed = (Current RX Bytes - Previous RX Bytes) / 3 seconds
62+
- TX Speed = (Current TX Bytes - Previous TX Bytes) / 3 seconds
63+
```
64+
65+
3. **Unit Conversion**
66+
The raw byte values are converted to human-readable formats using the following scale:
67+
- B/s (Bytes/second) : < 1024 B/s
68+
- KB/s (Kilobytes/second) : < 1024 KB/s
69+
- MB/s (Megabytes/second) : < 1024 MB/s
70+
- GB/s (Gigabytes/second) : ≥ 1024 MB/s
71+
72+
### Implementation Details
73+
- Update Interval: 3 seconds (configurable via `UPDATE_INTERVAL_SECONDS`)
74+
- Interface Filtering: Uses prefix matching to exclude virtual interfaces
75+
- Error Handling: Continues operation even if a single reading fails
76+
- Memory Usage: Maintains only previous reading state (2 integers)
77+
- Display Format: "↓ {download_speed} ↑ {upload_speed}"
78+
79+
### Resource Usage
80+
- CPU Impact: Minimal (reads one file every 3 seconds)
81+
- Memory Footprint: Constant (independent of network activity)
82+
- I/O Operations: One file read per update interval
83+
84+
## Contributing
85+
86+
Contributions are welcome to the Network Speed Monitor extension! To contribute, follow these steps:
87+
88+
1. **Fork the repository.**
89+
2. **Clone your fork:**
90+
91+
```sh
92+
git clone https://github.com/YOUR-USERNAME/netspeed-monitor.git
93+
```
94+
95+
3. **Create a new branch:**
96+
97+
```sh
98+
git checkout -b my-feature-branch
99+
```
100+
101+
4. **Make your changes.**
102+
5. **Test your changes.**
103+
6. **Commit your changes:**
104+
105+
```sh
106+
git add .
107+
git commit -m "Description of your changes"
108+
```
11109

12-
## Development
110+
7. **Push your changes:**
13111

14-
To make changes to the extension or contribute to its development, follow these steps:
112+
```sh
113+
git push origin my-feature-branch
114+
```
15115

16-
1. Make sure you have the necessary development tools installed on your system.
17-
2. Clone the repository to your local machine.
18-
3. Modify the extension code using your preferred text editor.
19-
4. Test the changes to ensure they work as expected.
20-
5. Create a pull request on the original repository to submit your changes for review.
116+
8. **Create a pull request.**
21117

22118
## License
23119

extension.js

Lines changed: 154 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,165 @@
1-
const { St, Clutter } = imports.gi;
2-
const Main = imports.ui.main;
3-
4-
const ExtensionUtils = imports.misc.extensionUtils;
5-
const Me = ExtensionUtils.getCurrentExtension();
6-
7-
const GLib = imports.gi.GLib;
8-
const ByteArray = imports.byteArray;
9-
10-
const refreshInterval = 3;
11-
12-
let textDisplay;
13-
let lastTotalRxBytes = 0;
14-
let lastTotalTxBytes = 0;
15-
16-
function init() {
17-
textDisplay = new St.Label({
18-
style_class: 'network-speed-label',
19-
"y_align": Clutter.ActorAlign.CENTER,
20-
text: '↓ 0 ↑ 0',
21-
});
22-
}
23-
24-
function enable() {
25-
Main.panel._rightBox.insert_child_at_index(textDisplay, 0);
26-
27-
updateNetworkSpeed();
28-
}
29-
30-
function disable() {
31-
Main.panel._rightBox.remove_child(textDisplay);
32-
}
33-
34-
function updateNetworkSpeed() {
35-
let [success, output] = GLib.spawn_command_line_sync('cat /proc/net/dev');
36-
if (success) {
37-
let lines = ByteArray.toString(output).split('\n');
38-
39-
let totalRxBytes = 0;
40-
let totalTxBytes = 0;
41-
42-
for (let i = 2; i < lines.length; i++) {
43-
let line = lines[i].trim();
44-
if (line.length === 0) continue;
45-
46-
let parts = line.split(':');
47-
if (parts.length !== 2) continue;
1+
'use strict';
2+
3+
// Import required GNOME Shell libraries
4+
import GObject from 'gi://GObject';
5+
import St from 'gi://St';
6+
import GLib from 'gi://GLib';
7+
import Clutter from 'gi://Clutter';
8+
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
9+
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
10+
11+
// Configuration constants
12+
const UPDATE_INTERVAL_SECONDS = 3;
13+
const NETWORK_INTERFACES_TO_IGNORE = ['lo', 'vir', 'vbox', 'docker', 'br-'];
14+
15+
/**
16+
* NetworkSpeedIndicator class - Displays network upload and download speeds
17+
* in the GNOME Shell panel
18+
*/
19+
const NetworkSpeedIndicator = GObject.registerClass(
20+
class NetworkSpeedIndicator extends St.Label {
21+
_init() {
22+
// Initialize the label with default styling and text
23+
super._init({
24+
style_class: 'network-speed-label',
25+
y_align: Clutter.ActorAlign.CENTER,
26+
text: '↓ 0 B/s ↑ 0 B/s'
27+
});
28+
29+
// Initialize state variables
30+
this._previousRxBytes = 0;
31+
this._previousTxBytes = 0;
32+
this._updateTimer = null;
33+
}
4834

49-
let interfaceName = parts[0].trim();
50-
if (
51-
interfaceName.startsWith('lo') || // Skip loopback interface
52-
interfaceName.startsWith('vir') || // Skip virtual interfaces
53-
interfaceName.startsWith('vbox') // Skip VirtualBox interfaces (adjust as needed)
54-
) {
55-
continue;
35+
/**
36+
* Converts bytes per second to human-readable format
37+
* @param {number} bytes - Bytes per second to format
38+
* @returns {string} Formatted speed string
39+
*/
40+
_formatSpeedValue(bytes) {
41+
const units = ['B/s', 'KB/s', 'MB/s', 'GB/s'];
42+
let unitIndex = 0;
43+
let speed = bytes;
44+
45+
// Convert to appropriate unit
46+
while (speed >= 1024 && unitIndex < units.length - 1) {
47+
speed /= 1024;
48+
unitIndex++;
5649
}
57-
58-
let data = parts[1].trim().split(/\s+/);
59-
let rxBytes = parseInt(data[0]);
60-
let txBytes = parseInt(data[8]);
61-
62-
totalRxBytes += rxBytes;
63-
totalTxBytes += txBytes;
64-
50+
51+
return `${speed.toFixed(1)} ${units[unitIndex]}`;
6552
}
6653

67-
if (lastTotalRxBytes == 0) {
68-
lastTotalRxBytes = totalRxBytes;
69-
}
70-
if (lastTotalTxBytes == 0) {
71-
lastTotalTxBytes = totalTxBytes;
54+
/**
55+
* Checks if a network interface should be excluded from calculations
56+
* @param {string} interfaceName - Name of the network interface
57+
* @returns {boolean} True if interface should be ignored
58+
*/
59+
_isIgnoredInterface(interfaceName) {
60+
return NETWORK_INTERFACES_TO_IGNORE.some(prefix =>
61+
interfaceName.startsWith(prefix)
62+
);
7263
}
7364

74-
let rxSpeed = formatNetworkSpeed((totalRxBytes - lastTotalRxBytes) / refreshInterval);
75-
let txSpeed = formatNetworkSpeed((totalTxBytes - lastTotalTxBytes) / refreshInterval);
76-
77-
textDisplay.text = `↓ ${rxSpeed}${txSpeed}`;
78-
79-
lastTotalRxBytes = totalRxBytes;
80-
lastTotalTxBytes = totalTxBytes;
81-
82-
}
65+
/**
66+
* Updates the network speed display
67+
* @returns {boolean} Always returns true to keep the update timer running
68+
*/
69+
_updateSpeed() {
70+
try {
71+
// Read network statistics from /proc/net/dev
72+
const [success, output] = GLib.spawn_command_line_sync('cat /proc/net/dev');
73+
if (!success) return GLib.SOURCE_CONTINUE;
74+
75+
// Parse network statistics
76+
const lines = new TextDecoder().decode(output).split('\n');
77+
let totalRxBytes = 0;
78+
let totalTxBytes = 0;
79+
80+
// Process each interface's data (skip header lines)
81+
for (const line of lines.slice(2)) {
82+
const trimmed = line.trim();
83+
if (!trimmed) continue;
84+
85+
const [iface, data] = trimmed.split(':');
86+
if (!data || this._isIgnoredInterface(iface)) continue;
87+
88+
// Extract rx and tx bytes from statistics
89+
const [rxBytes, , , , , , , , txBytes] = data.trim()
90+
.split(/\s+/)
91+
.map(n => parseInt(n, 10));
92+
93+
totalRxBytes += rxBytes;
94+
totalTxBytes += txBytes;
95+
}
96+
97+
// Initialize previous values if first run
98+
this._previousRxBytes ||= totalRxBytes;
99+
this._previousTxBytes ||= totalTxBytes;
100+
101+
// Calculate current speeds
102+
const downloadSpeed = this._formatSpeedValue(
103+
(totalRxBytes - this._previousRxBytes) / UPDATE_INTERVAL_SECONDS
104+
);
105+
const uploadSpeed = this._formatSpeedValue(
106+
(totalTxBytes - this._previousTxBytes) / UPDATE_INTERVAL_SECONDS
107+
);
108+
109+
// Update the display
110+
this.text = `↓ ${downloadSpeed}${uploadSpeed}`;
111+
112+
// Store current values for next update
113+
this._previousRxBytes = totalRxBytes;
114+
this._previousTxBytes = totalTxBytes;
115+
} catch (error) {
116+
console.error('NetworkSpeed:', error);
117+
}
83118

84-
// Update every 'refreshInterval' seconds (adjust the interval as needed)
85-
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, refreshInterval, updateNetworkSpeed);
86-
}
119+
return GLib.SOURCE_CONTINUE;
120+
}
87121

88-
function formatNetworkSpeed(bytes) {
89-
const suffixes = ['B/s', 'KB/s', 'MB/s', 'GB/s'];
90-
let index = 0;
122+
/**
123+
* Starts periodic updates of the network speed display
124+
*/
125+
startUpdate() {
126+
this._updateSpeed();
127+
this._updateTimer = GLib.timeout_add_seconds(
128+
GLib.PRIORITY_DEFAULT,
129+
UPDATE_INTERVAL_SECONDS,
130+
this._updateSpeed.bind(this)
131+
);
132+
}
91133

92-
while (bytes >= 1024 && index < suffixes.length - 1) {
93-
bytes /= 1024;
94-
index++;
134+
/**
135+
* Stops periodic updates of the network speed display
136+
*/
137+
stopUpdate() {
138+
if (this._updateTimer) {
139+
GLib.source_remove(this._updateTimer);
140+
this._updateTimer = null;
141+
}
142+
}
95143
}
144+
);
145+
146+
/**
147+
* Main extension class that handles initialization and cleanup
148+
*/
149+
export default class NetworkSpeedExtension extends Extension {
150+
enable() {
151+
// Create and add the indicator to the panel
152+
this._indicator = new NetworkSpeedIndicator();
153+
Main.panel._rightBox.insert_child_at_index(this._indicator, 0);
154+
this._indicator.startUpdate();
155+
}
96156

97-
return `${bytes.toFixed(2)} ${suffixes[index]}`;
98-
}
157+
disable() {
158+
// Clean up when the extension is disabled
159+
if (this._indicator) {
160+
this._indicator.stopUpdate();
161+
this._indicator.destroy();
162+
this._indicator = null;
163+
}
164+
}
165+
}

0 commit comments

Comments
 (0)