Skip to content

Commit

Permalink
added a network widget that display sent & received megabytes per sec…
Browse files Browse the repository at this point in the history
…ond as well as a graph of the total throughput per second
  • Loading branch information
seidnerj committed Apr 7, 2022
1 parent dc116af commit fa7ce9c
Show file tree
Hide file tree
Showing 18 changed files with 566 additions and 416 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ name: Test

on: [
pull_request,
push
push,
workflow_dispatch
]

jobs:
Expand All @@ -28,6 +29,8 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: echo npm version "$(npm --version)"
- run: echo node version "$(node --version)"
- run: npm ci
- run: npm run build:server
- run: npm run lint:server
Expand Down Expand Up @@ -61,4 +64,4 @@ jobs:
Start-Sleep -s 30
- name: 'Test hb-service install'
run: node dist/bin/hb-service.js status --port 8581


2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Discord](https://badgen.net/discord/online-members/C87Pvq3?icon=discord&label=discord)](https://discord.gg/C87Pvq3)
[![Donate](https://badgen.net/badge/donate/paypal/yellow)](https://paypal.me/oznu)

Supported Languages: :gb: :de: :fr: :poland: :czech_republic: :ru: :cn: :hungary: :jp: :es: :netherlands: :tr: :it: :bulgaria: :sweden: :norway: :slovenia: :brazil: :portugal: :indonesia: :kr: :macedonia: :thailand:
Supported Languages: :gb: :de: :fr: :poland: :czech_republic: :ru: :cn: :hungary: :jp: :es: :netherlands: :tr: :it: :bulgaria: :sweden: :norway: :slovenia: :brazil: :portugal: :indonesia: :kr: :macedonia: :thailand: :israel:

# Homebridge Config UI X

Expand Down
653 changes: 283 additions & 370 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/modules/status/status.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export class StatusController {
return this.statusService.getServerMemoryInfo();
}

@ApiOperation({ summary: 'Return a history of transmitted & received bytes per second as well as the latest value.' })
@Get('/network')
getServerNetworkInfo() {
return this.statusService.getServerNetworkInfo();
}

@ApiOperation({ summary: 'Return the host and process (UI) uptime.' })
@Get('/uptime')
getServerUptimeInfo() {
Expand Down
9 changes: 9 additions & 0 deletions src/modules/status/status.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ export class StatusGateway {
}
}

@SubscribeMessage('get-server-network-info')
async getServerNetworkInfo(client, payload) {
try {
return await this.statusService.getServerNetworkInfo();
} catch (e) {
return new WsException(e.message);
}
}

@SubscribeMessage('get-server-uptime-info')
async getServerUptimeInfo(client, payload) {
try {
Expand Down
42 changes: 42 additions & 0 deletions src/modules/status/status.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ export class StatusService {

private cpuLoadHistory: number[] = [];
private memoryUsageHistory: number[] = [];
private networkUsageHistory: number[] = [];

private memoryInfo: si.Systeminformation.MemData;
private networkInfo: si.Systeminformation.NetworkStatsData;

constructor(
private httpService: HttpService,
Expand All @@ -51,6 +53,12 @@ export class StatusService {
this.getCpuLoadPoint();
this.getMemoryUsagePoint();
}, 10000);

// poll network usage once per second so we have correct per/second figures
setInterval(async () => {
this.getNetworkUsagePoint();
}, 1000);

} else {
this.logger.warn('Server metrics monitoring disabled.');
}
Expand All @@ -72,6 +80,26 @@ export class StatusService {
this.cpuLoadHistory.push(currentLoad);
}

/**
* Looks up the current network usage and stores the last 60 points
*/
private async getNetworkUsagePoint() {
// TODO: aggregate stats for all interfaces and not just the default
// interface (even better - be able to specify in the UI which interfaces to aggregate)
const defaultInterfaceName = await si.networkInterfaceDefault();

const net = await si.networkStats(defaultInterfaceName);
this.networkInfo = net[0];

// TODO: be able to specify unit size (i.e. bytes, megabytes, gigabytes)
const tx_rx_sec = (net[0].tx_sec + net[0].rx_sec) / 1024 / 1024;

// TODO: break out the sent and received figures to two separate stacked
// graphs (these should ideally be positive/negative mirrored linecharts)
this.networkUsageHistory = this.networkUsageHistory.slice(-60);
this.networkUsageHistory.push(tx_rx_sec);
}

/**
* Looks up the current memory usage and stores the last 60 points
*/
Expand Down Expand Up @@ -192,6 +220,20 @@ export class StatusService {
};
}

/**
* Returns server Network usage information
*/
public async getServerNetworkInfo() {
if (!this.networkUsageHistory.length) {
await this.getNetworkUsagePoint();
}

return {
net: this.networkInfo,
networkUsageHistory: this.networkUsageHistory,
};
}

/**
* Returns server and process uptime information
*/
Expand Down
12 changes: 9 additions & 3 deletions test/e2e/config-editor.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ describe('ConfigEditorController (e2e)', () => {

// check the updates were saved to disk and mistakes corrected
const savedConfig: HomebridgeConfig = await fs.readJson(configFilePath);
expect(savedConfig.bridge.username).toEqual(originalUsername);
expect(savedConfig.bridge.username).toBe(originalUsername);
});

it('POST /config-editor (accept bridge.username if valid value is provided)', async () => {
Expand Down Expand Up @@ -345,7 +345,7 @@ describe('ConfigEditorController (e2e)', () => {

// check the updates were saved to disk and mistakes corrected
const savedConfig: HomebridgeConfig = await fs.readJson(configFilePath);
expect(savedConfig.bridge.pin).toEqual(originalPin);
expect(savedConfig.bridge.pin).toBe(originalPin);
});

it('POST /config-editor (accept bridge.pin if a valid value is provided)', async () => {
Expand Down Expand Up @@ -866,7 +866,13 @@ describe('ConfigEditorController (e2e)', () => {
},
});

const newbackupCount = (await fs.readdir(backupFilePath)).length;
// there is a race condition here whereby we might read the backup file
// path before the deletion has actually happened, causing the test to fail,
// so I have added a 1 second delay.
await new Promise((resolve) => setTimeout(resolve, 1000));

const backups = await fs.readdir(backupFilePath);
const newbackupCount = backups.length;

expect(newbackupCount).toBe(0);
expect(res.statusCode).toBe(200);
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/server.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ describe('ServerController (e2e)', () => {

expect(res.statusCode).toBe(200);
expect(Array.isArray(res.json())).toBe(true);
}, 15000);
}, 30000);

it('GET /server/network-interfaces/bridge', async () => {
const res = await app.inject({
Expand Down
22 changes: 18 additions & 4 deletions test/e2e/status.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('StatusController (e2e)', () => {
expect(res.json()).toHaveProperty('cpuLoadHistory');
expect(res.json()).toHaveProperty('cpuTemperature');
expect(res.json()).toHaveProperty('currentLoad');
});
}, 30000);

it('GET /status/ram', async () => {
const res = await app.inject({
Expand All @@ -92,7 +92,21 @@ describe('StatusController (e2e)', () => {
expect(res.statusCode).toBe(200);
expect(res.json()).toHaveProperty('mem');
expect(res.json()).toHaveProperty('memoryUsageHistory');
});
}, 30000);

it('GET /status/network', async () => {
const res = await app.inject({
method: 'GET',
path: '/status/network',
headers: {
authorization,
},
});

expect(res.statusCode).toBe(200);
expect(res.json()).toHaveProperty('net');
expect(res.json()).toHaveProperty('networkUsageHistory');
}, 30000);

it('GET /status/uptime', async () => {
const res = await app.inject({
Expand Down Expand Up @@ -169,8 +183,8 @@ describe('StatusController (e2e)', () => {

expect(res.statusCode).toBe(200);
expect(res.json()).toHaveProperty('serviceUser');
expect(res.json().homebridgeConfigJsonPath).toEqual(process.env.UIX_CONFIG_PATH);
expect(res.json().homebridgeStoragePath).toEqual(process.env.UIX_STORAGE_PATH);
expect(res.json().homebridgeConfigJsonPath).toBe(process.env.UIX_CONFIG_PATH);
expect(res.json().homebridgeStoragePath).toBe(process.env.UIX_STORAGE_PATH);
}, 30000);

it('GET /status/nodejs', async () => {
Expand Down
3 changes: 1 addition & 2 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ui/src/app/modules/status/status.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ gridster {
}

#CpuWidgetComponent,
#NetworkWidgetComponent,
#MemoryWidgetComponent,
#UptimeWidgetComponent {
height: unset !important;
Expand Down
66 changes: 34 additions & 32 deletions ui/src/app/modules/status/status.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { HapQrcodeWidgetComponent } from './widgets/hap-qrcode-widget/hap-qrcode
import { HomebridgeLogsWidgetComponent } from './widgets/homebridge-logs-widget/homebridge-logs-widget.component';
import { TerminalWidgetComponent } from './widgets/terminal-widget/terminal-widget.component';
import { CpuWidgetComponent } from './widgets/cpu-widget/cpu-widget.component';
import { NetworkWidgetComponent } from './widgets/network-widget/network-widget.component';
import { MemoryWidgetComponent } from './widgets/memory-widget/memory-widget.component';
import { UptimeWidgetComponent } from './widgets/uptime-widget/uptime-widget.component';
import { HomebridgeStatusWidgetComponent } from './widgets/homebridge-status-widget/homebridge-status-widget.component';
Expand All @@ -30,37 +31,38 @@ import { ClockWidgetComponent } from './widgets/clock-widget/clock-widget.compon
import { ChildBridgeWidgetComponent } from './widgets/child-bridge-widget/child-bridge-widget.component';

@NgModule({
declarations: [
StatusComponent,
WidgetsComponent,
WidgetAddComponent,
WidgetControlComponent,
HapQrcodeWidgetComponent,
HomebridgeLogsWidgetComponent,
TerminalWidgetComponent,
CpuWidgetComponent,
MemoryWidgetComponent,
UptimeWidgetComponent,
HomebridgeStatusWidgetComponent,
SystemInfoWidgetComponent,
WeatherWidgetComponent,
AccessoriesWidgetComponent,
ClockWidgetComponent,
ChildBridgeWidgetComponent,
],
imports: [
CommonModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
TranslateModule.forChild(),
NgbModule,
GridsterModule,
DragulaModule,
ChartsModule,
CoreModule,
AccessoriesCoreModule,
ManagePluginsModule,
],
declarations: [
StatusComponent,
WidgetsComponent,
WidgetAddComponent,
WidgetControlComponent,
HapQrcodeWidgetComponent,
HomebridgeLogsWidgetComponent,
TerminalWidgetComponent,
CpuWidgetComponent,
MemoryWidgetComponent,
NetworkWidgetComponent,
UptimeWidgetComponent,
HomebridgeStatusWidgetComponent,
SystemInfoWidgetComponent,
WeatherWidgetComponent,
AccessoriesWidgetComponent,
ClockWidgetComponent,
ChildBridgeWidgetComponent,
],
imports: [
CommonModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
TranslateModule.forChild(),
NgbModule,
GridsterModule,
DragulaModule,
ChartsModule,
CoreModule,
AccessoriesCoreModule,
ManagePluginsModule,
],
})
export class StatusModule { }
8 changes: 8 additions & 0 deletions ui/src/app/modules/status/widget-add/widget-add.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ export class WidgetAddComponent implements OnInit {
rows: 3,
mobileOrder: 50,
},
{
name: this.translate.instant('status.network.title_network'),
component: 'NetworkWidgetComponent',
hidden: false,
cols: 5,
rows: 3,
mobileOrder: 110,
},
{
name: this.translate.instant('status.uptime.title_uptime'),
component: 'UptimeWidgetComponent',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div class="flex-column d-flex align-items-stretch h-100 w-100 pb-1">
<div style="cursor: move;" class="drag-handler pl-2 pt-1 pr-2" [translate]="'status.network.title_network'">
Network
</div>
<canvas class="widget-chart h-100 w-100" baseChart [datasets]="lineChartData" [labels]="lineChartLabels"
[options]="lineChartOptions" [colors]="lineChartColors" [chartType]="'line'"></canvas>
<div #widgetbackground class="hb-widget-chart-background"></div>
<div class="d-flex flex-row flex-grow-1 align-items-center w-100 gridster-item-content text-center">
<div class="d-flex justify-content-around flex-wrap w-100">
<div class="text-center widget-value-parent-wrap">
<div class="widget-value mb-0">{{ receivedPerSec | number:'1.0-2' }} MB</div>
<div class="widget-value-label grey-text" [translate]="'status.network.label_received_per_second'">Received/sec
</div>
</div>
<div class="text-center widget-value-parent-wrap">
<div class="widget-value mb-0">
{{ sentPerSec | number:'1.0-2' }} MB
</div>
<div class="widget-value-label grey-text" [translate]="'status.network.label_sent_per_second'">Sent/sec</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.widget-chart {
position: absolute;
z-index: -1;
}
Loading

4 comments on commit fa7ce9c

@xrust83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add ukraine flags ;-)

@seidnerj
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add ukraine flags ;-)

Is Ukrainian currently supported? If so just add the flag and create a pull request.

@xrust83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/oznu/homebridge-config-ui-x/releases/tag/4.41.3
I do not know how to do it but the language has been supported for a long time, I promto sent it to the author but did not do OL, if you do not find it difficult to insert the flag

@seidnerj
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/oznu/homebridge-config-ui-x/releases/tag/4.41.3
I do not know how to do it but the language has been supported for a long time, I promto sent it to the author but did not do OL, if you do not find it difficult to insert the flag

I see you figured it out 👏

Please sign in to comment.