You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
12 KiB
318 lines
12 KiB
import {Component, OnInit} from "@angular/core";
|
|
import {HttpClient} from "@angular/common/http";
|
|
import {PacketGroup} from "../../entities/PacketGroup";
|
|
import {Chart} from "chart.js/auto";
|
|
import {devicesToRequest, numToColor} from "../../utils/Utils";
|
|
import {KeyValueMap} from "../../entities/KeyValueMap";
|
|
import {NodeDTO} from "../../entities/NodeDTO";
|
|
import {ActivatedRoute} from "@angular/router";
|
|
import {PacketSignalDTO} from "../../entities/PacketSignalDTO";
|
|
import {DatePipe} from "@angular/common";
|
|
|
|
@Component({
|
|
selector: "app-network-status",
|
|
template: `
|
|
<div class="width-vw width-padding">
|
|
<div [ngSwitch]="MODE">
|
|
<h1 *ngSwitchCase="'ALL'">Статистика всей сети (желательно нажать ф5 если до этого смотрели другую ноду)</h1>
|
|
<h1 *ngSwitchCase="'NODE'">Статистика ноды {{getNumName(NUM)}} в сети</h1>
|
|
</div>
|
|
<div *ngIf="MODE == 'NODE'">
|
|
<div>
|
|
<mat-card>
|
|
<mat-card-actions>
|
|
<mat-radio-group [(ngModel)]="signalMode" (ngModelChange)="this.updateSignalGraph()" aria-label="Select an option">
|
|
<mat-radio-button value="day">За день</mat-radio-button>
|
|
<mat-radio-button value="week">За неделю</mat-radio-button>
|
|
<mat-radio-button value="month">За месяц</mat-radio-button>
|
|
</mat-radio-group>
|
|
</mat-card-actions>
|
|
<mat-card-content>
|
|
<canvas [id]="signalCanvasId">{{signalChart}}</canvas>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
</div>
|
|
</div>
|
|
<div *ngFor="let type of graphs" >
|
|
<div *ngIf="MODE == type.requestMode" class="card-wrapper-450" style="padding-top: 12px">
|
|
<mat-card *ngFor="let p1 of type.cards">
|
|
<mat-card-content>
|
|
<canvas [id]="p1.canvasId">{{p1.chart}}</canvas>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`
|
|
})
|
|
export class NetworkStatusComponent implements OnInit {
|
|
DAY = 86400;
|
|
WEEK = this.DAY * 7;
|
|
MONTH = this.DAY * 30;
|
|
MODE: "ALL"|"NODE" = "ALL"
|
|
NUM:number = 0;
|
|
|
|
signalMode:"day"|"month"|"week"|string = "day"
|
|
signalCanvasId = "signalCanvasId";
|
|
signalChart = {
|
|
chart: null as unknown as Chart,
|
|
config: this.generateConfigTChart("Проходимость сигнала", true, "line") as any
|
|
};
|
|
|
|
nodesNames: KeyValueMap<NodeDTO> = {}
|
|
|
|
//общая статичтика по perPortNum за день\неделю\месяц / ?=
|
|
//top кто насрал пакетами всего за день\неделю\месяц / ?=packetsSumNode=true
|
|
graphs:any[] = this.generateGraps();
|
|
constructor(private http: HttpClient,
|
|
private route: ActivatedRoute,
|
|
private datepipe: DatePipe) {}
|
|
|
|
getNumName(num:number) {
|
|
if (`${num}` in this.nodesNames)
|
|
return this.nodesNames[`${num}`].long_name
|
|
else return `${num}`
|
|
}
|
|
|
|
generateGraps() {
|
|
return [
|
|
{
|
|
header: "Cтатистика пакетов в сети",
|
|
type: 'perPortNum',
|
|
requestMode: "ALL",
|
|
endpoint:"api/packet/stats",
|
|
cards:[{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "DayPerPB",
|
|
params: "?=",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.DAY,
|
|
config: this.generateConfigTChart("Cтатистика по пакетам в сети за день")
|
|
},{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "WeekPerPB",
|
|
params: "?=",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.WEEK,
|
|
config: this.generateConfigTChart("Cтатистика по пакетам в сети за неделю")
|
|
},{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "MonthPerPB",
|
|
params: "?=",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.MONTH,
|
|
config: this.generateConfigTChart("Cтатистика по пакетам в сети за месяц")
|
|
}]
|
|
},
|
|
{
|
|
header: "Общая статистика пакетов в сети",
|
|
type: 'perSumNode',
|
|
requestMode: "ALL",
|
|
endpoint:"api/packet/stats",
|
|
cards:[{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "DaySumPB",
|
|
params: "?packetsSumNode=true",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.DAY,
|
|
config: this.generateConfigTChart("Количество пакетов от пользоватей за день", false)
|
|
},{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "WeekSumPB",
|
|
params: "?packetsSumNode=true",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.WEEK,
|
|
config: this.generateConfigTChart("Количество пакетов от пользоватей за неделю", false)
|
|
},{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "MonthSumPB",
|
|
params: "?packetsSumNode=true",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.MONTH,
|
|
config: this.generateConfigTChart("Количество пакетов от пользоватей за месяц", false)
|
|
}]
|
|
},{
|
|
header: "Cтатистика пакетов в сети",
|
|
type: 'packetsPerNode',
|
|
requestMode: "NODE",
|
|
endpoint:"api/packet/stats",
|
|
cards:[{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "DayPerNodePB",
|
|
params: "?packetsPerNode=true",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.DAY,
|
|
config: this.generateConfigTChart("Cтатистика по пакетам в сети за день")
|
|
},{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "WeekPerNodePB",
|
|
params: "?packetsPerNode=true",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.WEEK,
|
|
config: this.generateConfigTChart("Cтатистика по пакетам в сети за неделю")
|
|
},{
|
|
chart: null as unknown as Chart,
|
|
canvasId: "MonthPerNodePB",
|
|
params: "?packetsPerNode=true",
|
|
before: new Date().getTime()/1000,
|
|
after: (new Date().getTime()/1000) - this.MONTH,
|
|
config: this.generateConfigTChart("Cтатистика по пакетам в сети за месяц")
|
|
}]
|
|
}
|
|
]
|
|
}
|
|
|
|
generateConfigTChart(name: string, legend: boolean = true, type: string = "pie") {
|
|
return {
|
|
type: type,
|
|
data: {
|
|
labels: [] as any[],
|
|
datasets: [] as any[]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
plugins: {
|
|
legend: {
|
|
position: 'bottom',
|
|
display: legend
|
|
},
|
|
title: {
|
|
display: true,
|
|
text: name
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ngOnInit(): void {
|
|
this.route.params.subscribe(
|
|
(params) => {
|
|
const num: number = Number.parseInt(params["num"]);
|
|
switch (num) {
|
|
case 0: {
|
|
this.MODE = "ALL";
|
|
this.http.get(`api/nodes/list?q=${devicesToRequest()}`).subscribe(
|
|
(obj) => {
|
|
(obj as NodeDTO[]).forEach(
|
|
(node) => {
|
|
this.nodesNames[`${node.num}`] = node;
|
|
}
|
|
)
|
|
}
|
|
).add(
|
|
() => {
|
|
this.graphs = this.generateGraps();
|
|
this.updateGraphs();
|
|
}
|
|
)
|
|
break;
|
|
}
|
|
default: {
|
|
this.MODE = "NODE";
|
|
this.NUM = num;
|
|
this.http.get(`api/nodes/${num}?q=${devicesToRequest()}`).subscribe(
|
|
(obj) => {
|
|
const node: NodeDTO = obj as NodeDTO
|
|
if (node)
|
|
this.nodesNames[`${node.num}`] = node;
|
|
}
|
|
).add(
|
|
() => {
|
|
this.graphs = this.generateGraps();
|
|
this.updateGraphs();
|
|
this.updateSignalGraph();
|
|
}
|
|
)
|
|
break;
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
updateSignalGraph() {
|
|
const before = new Date().getTime() / 1000;
|
|
let after;
|
|
switch (this.signalMode) {
|
|
case "day": {
|
|
after = (new Date().getTime()/1000) - this.DAY;
|
|
break;
|
|
}
|
|
case "week": {
|
|
after = (new Date().getTime()/1000) - this.WEEK;
|
|
break;
|
|
}
|
|
case "month": {
|
|
after = (new Date().getTime()/1000) - this.MONTH;
|
|
break;
|
|
}
|
|
}
|
|
this.http.get(`api/packet/signal?before=${before}&after=${after}&nums=${this.NUM}${devicesToRequest()}`).subscribe(
|
|
(obj) => {
|
|
this.signalChart.config.data = {labels: [], datasets:[{label: "snr",data:[]},{label: "rssi",data:[]}]};
|
|
(obj as PacketSignalDTO[]).forEach(
|
|
(packet: PacketSignalDTO) => {
|
|
this.signalChart.config.data.labels.push(this.datepipe.transform(packet.ts*1000, 'HH:mm dd.MM.yyyy'))
|
|
this.signalChart.config.data.datasets[0].data.push(packet.rx_snr)
|
|
this.signalChart.config.data.datasets[1].data.push(packet.rx_rssi)
|
|
return;
|
|
}
|
|
)
|
|
if (this.signalChart.chart != null)
|
|
this.signalChart.chart.destroy()
|
|
|
|
this.signalChart.chart = new Chart(this.signalCanvasId, this.signalChart.config)
|
|
}
|
|
)
|
|
}
|
|
|
|
updateGraphs() {
|
|
this.graphs.forEach(
|
|
(graph) => {
|
|
graph.cards.forEach((settings:any) => {
|
|
if (this.MODE != graph.requestMode) return;
|
|
this.http.get(`${graph.endpoint}${settings.params}&before=${settings.before}&after=${settings.after}&${this.NUM == 0?'':('&nums='+this.NUM)}${devicesToRequest()}`)
|
|
.subscribe((data) => {
|
|
settings.config.data = {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: settings.canvasId,
|
|
data: [],
|
|
backgroundColor: []
|
|
}
|
|
]
|
|
};
|
|
(data as Object[]).map((obj) => PacketGroup.fromDto(obj)).sort((p1, p2) => p2.count - p1.count).forEach(
|
|
(d) => {
|
|
switch (graph.type) {
|
|
case "perPortNum":
|
|
case "packetsPerNode":{
|
|
settings.config.data.labels.push(`${d.portnumName} - ${d.count}`)
|
|
settings.config.data.datasets[0].data.push(d.count)
|
|
settings.config.data.datasets[0].backgroundColor.push(numToColor(d.portnum, 0))
|
|
break;
|
|
}
|
|
case "perSumNode": {
|
|
const name = `${d.from}` in this.nodesNames ? this.nodesNames[`${d.from}`].long_name : `${d.from}`
|
|
settings.config.data.labels.push(`${name} - ${d.count}`)
|
|
settings.config.data.datasets[0].data.push(d.count)
|
|
settings.config.data.datasets[0].backgroundColor.push(numToColor(d.from, 0))
|
|
break;
|
|
}
|
|
default: {
|
|
console.log("missing type: " + graph.type);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
)
|
|
if (settings.chart)
|
|
settings.chart.destroy()
|
|
settings.chart = new Chart(settings.canvasId, settings.config)
|
|
})
|
|
})
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|