Add radio support

This commit is contained in:
sepehr 2024-07-20 16:11:27 +03:30
parent 8d4a8f453d
commit d593919fc0
6 changed files with 167 additions and 48 deletions

View file

@ -9,17 +9,24 @@
<c-card class="mb-1"> <c-card class="mb-1">
<c-card-header> <c-card-header>
<c-row> <c-row>
<c-col md="3"> <c-col md="6" sm="12" style="display: flex;flex-direction: row;align-items: center;">
<h3>{{devdata['name'] }}<small style="font-size: 50%;"> ( {{devdata['ip'] }} )</small></h3> <h4 style="height: 100%;line-height: 170%;margin: 0;">{{devdata['name'] }}<small style="font-size: 50%;"> ( {{devdata['ip'] }} )</small></h4>
</c-col> </c-col>
<c-col md="9" class="justify-content-end" style="text-align: end;"> <c-col md="6" sm="12" class="justify-content-end" style="display: flex;flex-direction: row;align-items: center;">
<c-button-group class="mb-2" aria-label="Upate interval" role="group"> <c-button-group size="sm" aria-label="Upate interval" role="group">
<button cButton color="primary" (click)="delta='5m';updateData()" [active]="delta=='5m'">5 minute</button> <button cButton color="primary" size="sm" (click)="delta='5m';updateData()" [active]="delta=='5m'">5 minute</button>
<button cButton color="primary" (click)="delta='1h';updateData()" [active]="delta=='1h'">Hourly</button> <button cButton color="primary" size="sm" (click)="delta='1h';updateData()" [active]="delta=='1h'">Hourly</button>
<button cButton color="primary" (click)="delta='daily';updateData()" <button cButton color="primary" size="sm" (click)="delta='daily';updateData()"
[active]="delta=='daily'">Daily</button> [active]="delta=='daily'">Daily</button>
<button cButton color="primary" (click)="delta='live';updateData()" [active]="delta=='live'">Live</button> <button cButton color="primary" (click)="delta='live';updateData()" [active]="delta=='live'">Live</button>
</c-button-group> </c-button-group>
<c-form-check (click)="switch_total()" sizing="xl" class="mx-2" switch>
<input cFormCheckInput [checked]="total_type=='bps'" type="checkbox" />
<label cFormCheckLabel>
<span *ngIf="total_type=='bps'">Total bbs</span>
<span *ngIf="total_type!='bps'">Total pps</span>
</label>
</c-form-check>
</c-col> </c-col>
</c-row> </c-row>
@ -38,25 +45,14 @@
<c-card-body> <c-card-body>
<c-row style="flex-direction:row"> <c-row style="flex-direction:row">
<ng-container *ngFor="let item of devdata | keyvalue; index as i"> <ng-container *ngFor="let item of devdata | keyvalue; index as i">
<!-- <c-col *ngIf="checkitem(item)" class="mb-2" >
<c-card color="dark" textColor="white" class="h-100 ">
<c-card-header style="padding: 5px 0 2px 9px;text-transform: capitalize;">{{item.key}}</c-card-header>
<c-card-body class="bg-gradient" style="padding:2px 0 2px 9px;">
<p cCardText>{{item.value}}</p>
</c-card-body>
</c-card>
</c-col> -->
<c-input-group *ngIf="checkitem(item)" class="mr-0 ml-0 mb-1" <c-input-group *ngIf="checkitem(item)" class="mr-0 ml-0 mb-1"
style="padding-right:unset;width: auto;flex: 1 1 auto;flex-flow: nowrap;flex: unset;"> style="padding-right:unset;width: auto;flex: 1 1 auto;flex-flow: nowrap;flex: unset;">
<span <span
style="padding: 0.175rem 0.35rem;background-color:#4f5d73;text-transform: capitalize;color:#fff;font-size:0.7rem" style="padding: 0.175rem 0.35rem;background-color:#4f5d73;text-transform: capitalize;color:#fff;font-size:0.7rem"
cInputGroupText>{{item.key}}</span> cInputGroupText>{{item.key}}</span>
<!-- <input cFormControl disabled style="font-size:0.8rem" [value]="item.value"/> -->
<span _ngcontent-ng-c666080582="" cinputgrouptext="" <span _ngcontent-ng-c666080582="" cinputgrouptext=""
style="padding: 0.175rem 0.35rem;color: rgba(44, 56, 74, 0.95);font-size: 0.7rem;background-color: #d8dbe0;border-color: #b1b7c1;" style="padding: 0.175rem 0.35rem;color: rgba(44, 56, 74, 0.95);font-size: 0.7rem;background-color: #d8dbe0;border-color: #b1b7c1;"
class="input-group-text">{{ item.value }}</span> class="input-group-text">{{ item.value }}</span>
<!-- <span style="background-color:#4f5d73;text-transform: capitalize;color:#fff;font-size:0.8rem" cInputGroupText >{{item.key}}</span> -->
</c-input-group> </c-input-group>
</ng-container> </ng-container>
</c-row> </c-row>
@ -71,7 +67,7 @@
<c-card-body> <c-card-body>
<c-row style="flex-direction:row"> <c-row style="flex-direction:row">
<gui-grid [source]="interfaces" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel" <gui-grid [source]="interfaces" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel"
[rowSelection]="rowSelection" [autoResizeWidth]=true> [autoResizeWidth]=true>
<gui-grid-column header="Name" field="name"> <gui-grid-column header="Name" field="name">
<ng-template let-value="item.name" let-item="item" let-index="index"> <ng-template let-value="item.name" let-item="item" let-index="index">
@ -134,7 +130,7 @@
{{value}} {{value}}
</ng-template> </ng-template>
</gui-grid-column> </gui-grid-column>
<gui-grid-column header="Actions" field="action" width="100" align="center"> <gui-grid-column header="Actions" field="action" width="60" align="center">
<ng-template let-value="item.id" let-item="item" let-index="index"> <ng-template let-value="item.id" let-item="item" let-index="index">
<button cButton color="info" size="sm" (click)="show_interface_rate(item['default-name'])" <button cButton color="info" size="sm" (click)="show_interface_rate(item['default-name'])"
class="mx-1"><i class="fa-solid fa-chart-line"></i></button> class="mx-1"><i class="fa-solid fa-chart-line"></i></button>
@ -147,7 +143,82 @@
</c-col> </c-col>
</c-row> </c-row>
<c-row *ngIf="is_radio && !radio_loading">
<c-col xs md="12" *ngFor="let raddata of radio_devsensors | keyvalue">
<c-card class="mb-1">
<c-card-header><h6>Radio data</h6></c-card-header>
<c-card-body>
<h6>{{raddata.key}}</h6>
<app-widgets-dropdown [devicedata]=raddata.value></app-widgets-dropdown>
<c-row>
<c-col md="3">
<table small stripedColumns cTable>
<tbody>
<ng-container *ngFor="let d of raddata.value['data'] | keyvalue ; let i=index">
<tr *ngIf="i<objectlen(raddata.value['data'])/4">
<th style="width: 30%;text-wrap: nowrap;">{{d.key}}</th>
<td scope="row">{{d.value}}</td>
</tr>
</ng-container>
</tbody>
</table>
</c-col>
<c-col md="3">
<table small stripedColumns cTable>
<tbody>
<ng-container *ngFor="let d of raddata.value['data'] | keyvalue ; let i=index">
<tr *ngIf="i>=objectlen(raddata.value['data'])/4 && i<(objectlen(raddata.value['data'])/4)*2">
<th style="width: 30%;text-wrap: nowrap;">{{d.key}}</th>
<td scope="row">{{d.value}}</td>
</tr>
</ng-container>
</tbody>
</table>
</c-col>
<c-col md="3">
<table small stripedColumns cTable>
<tbody>
<ng-container *ngFor="let d of raddata.value['data'] | keyvalue ; let i=index">
<tr *ngIf="i>=(objectlen(raddata.value['data'])/4)*2 && i<(objectlen(raddata.value['data'])/4)*3">
<th style="width: 30%;text-wrap: nowrap;">{{d.key}}</th>
<td scope="row">{{d.value}}</td>
</tr>
</ng-container>
</tbody>
</table>
</c-col>
<c-col md="3">
<table small stripedColumns cTable>
<tbody>
<ng-container *ngFor="let d of raddata.value['data'] | keyvalue ; let i=index">
<tr *ngIf="i>=(objectlen(raddata.value['data'])/4)*3">
<th>{{d.key}}</th>
<td scope="row">{{d.value}}</td>
</tr>
</ng-container>
</tbody>
</table>
</c-col>
</c-row>
<c-row *ngIf="raddata.value['strength-at-rates']">
<c-col>
<table small borderless cTable>
<tbody>
<tr>
<th style="text-wrap: nowrap;vertical-align: middle;padding: 5px;border-radius: 5px;background-color: #3399ff36;">Strength at rates</th>
<td scope="row">
<c-badge color="info" style="font-size: 0.85em;" class="mx-1" *ngFor="let st of strangth_at_rate_extract(raddata.value['strength-at-rates'])">{{st}}</c-badge>
</td>
</tr>
</tbody>
</table>
</c-col>
</c-row>
</c-card-body>
</c-card>
</c-col>
</c-row>
<c-modal #staticBackdropModal backdrop="static" size="xl" [visible]="InterfaceChartModalVisible" <c-modal #staticBackdropModal backdrop="static" size="xl" [visible]="InterfaceChartModalVisible"
id="InterfaceChartModal"> id="InterfaceChartModal">

View file

@ -1,4 +1,4 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnDestroy, OnInit } from "@angular/core";
import { Router, ActivatedRoute } from "@angular/router"; import { Router, ActivatedRoute } from "@angular/router";
import { dataProvider } from "../../providers/mikrowizard/data"; import { dataProvider } from "../../providers/mikrowizard/data";
import { loginChecker } from "../../providers/login_checker"; import { loginChecker } from "../../providers/login_checker";
@ -27,14 +27,20 @@ interface IUser {
color: string; color: string;
} }
type radiodata = {
[key: string]: any;
};
@Component({ @Component({
templateUrl: "device.component.html", templateUrl: "device.component.html",
styleUrls: ["device.component.scss"], styleUrls: ["device.component.scss"],
}) })
export class DeviceComponent implements OnInit { export class DeviceComponent implements OnInit, OnDestroy {
public uid: number; public uid: number;
public uname: string; public uname: string;
public tz: string; public tz: string;
public ispro: boolean = false;
constructor( constructor(
private data_provider: dataProvider, private data_provider: dataProvider,
private route: ActivatedRoute, private route: ActivatedRoute,
@ -51,6 +57,7 @@ export class DeviceComponent implements OnInit {
_self.uid = res.uid; _self.uid = res.uid;
_self.uname = res.name; _self.uname = res.name;
_self.tz = res.tz; _self.tz = res.tz;
_self.ispro = res.ISPRO;
const userId = _self.uid; const userId = _self.uid;
if (res.role != "admin") { if (res.role != "admin") {
@ -66,17 +73,20 @@ export class DeviceComponent implements OnInit {
} }
public devdata: any; public devdata: any;
public devsensors: any; public devsensors: any;
public radio_devsensors: radiodata;
public columns: Array<GuiColumn> = []; public columns: Array<GuiColumn> = [];
public loading: boolean = true; public loading: boolean = true;
public radio_loading: boolean = true;
public InterfaceChartModalVisible: boolean = false; public InterfaceChartModalVisible: boolean = false;
public rows: any = []; public rows: any = [];
public Selectedrows: any; public Selectedrows: any;
public devid: number = 0; public devid: number = 0;
public data_interval: any; public data_interval: any;
public delta: string = "5m"; public delta: string = "live";
public total_type: string = "bps"; public total_type: string = "bps";
public interface_rate: any = {}; public interface_rate: any = {};
public options: any; public options: any;
public is_radio: boolean = false;
public sorting = { public sorting = {
enabled: true, enabled: true,
multiSorting: true, multiSorting: true,
@ -95,7 +105,12 @@ export class DeviceComponent implements OnInit {
sort: true, sort: true,
columnsManager: true, columnsManager: true,
}; };
objectlen(object:any){
return Object.keys(object).length;
}
strangth_at_rate_extract(data:string){
return data.split(',');
}
public infoPanel: GuiInfoPanel = { public infoPanel: GuiInfoPanel = {
enabled: true, enabled: true,
infoDialog: false, infoDialog: false,
@ -365,17 +380,23 @@ export class DeviceComponent implements OnInit {
logger(item: any) { logger(item: any) {
console.dir(item); console.dir(item);
} }
switch_total() {
this.total_type = this.total_type == "bps" ? "pps" : "bps";
this.updateData();
}
updateData(): void { updateData(): void {
var _self = this; var _self = this;
this.data_provider.get_dev_info(this.devid).then((res) => { this.data_provider.get_dev_info(this.devid).then((res) => {
_self.devdata = res; _self.devdata = res;
_self.interfaces = res.interfaces; _self.interfaces = res.interfaces;
if ("is_radio" in res) _self.is_radio = res.is_radio;
_self.data_provider _self.data_provider
.get_dev_sensors(_self.devid, _self.delta, _self.total_type) .get_dev_sensors(_self.devid, _self.delta, _self.total_type)
.then((res) => { .then((res) => {
_self.devsensors = res; _self.devsensors = res;
_self.loading = false; _self.loading = false;
}); });
if (_self.is_radio) _self.get_radio_data();
}); });
} }
checkitem(item: any) { checkitem(item: any) {
@ -416,6 +437,18 @@ export class DeviceComponent implements OnInit {
}); });
} }
get_radio_data() {
if(!this.ispro)
return;
var _self = this;
_self.data_provider
.get_dev_radio_sensors(_self.devid, _self.delta)
.then((res) => {
_self.radio_devsensors = res;
_self.radio_loading = false;
});
}
initDeviceInfo(): void { initDeviceInfo(): void {
var _self = this; var _self = this;
clearInterval(this.data_interval); clearInterval(this.data_interval);
@ -423,15 +456,20 @@ export class DeviceComponent implements OnInit {
this.data_interval = setInterval(() => { this.data_interval = setInterval(() => {
this.data_provider.get_dev_info(this.devid).then((res) => { this.data_provider.get_dev_info(this.devid).then((res) => {
_self.devdata = res; _self.devdata = res;
if ("is_radio" in res) _self.is_radio = res.is_radio;
_self.interfaces = res.interfaces; _self.interfaces = res.interfaces;
_self.data_provider _self.data_provider
.get_dev_sensors(_self.devid, _self.delta, _self.total_type) .get_dev_sensors(_self.devid, _self.delta, _self.total_type)
.then((res) => { .then((res) => {
_self.devsensors = res; _self.devsensors = res;
_self.loading = false; _self.loading = false;
if (_self.is_radio) _self.get_radio_data();
}); });
}); });
}, 1000000); }, 60000);
}
ngOnDestroy() {
clearInterval(this.data_interval);
} }
} }

View file

@ -11,6 +11,9 @@ import {
NavbarModule, NavbarModule,
AlertModule, AlertModule,
ModalModule, ModalModule,
TableModule,
UtilitiesModule,
BadgeModule
} from "@coreui/angular"; } from "@coreui/angular";
import { ChartjsModule } from "@coreui/angular-chartjs"; import { ChartjsModule } from "@coreui/angular-chartjs";
@ -36,6 +39,9 @@ import { WidgetsModule } from "../widgets/widgets.module";
GuiGridModule, GuiGridModule,
NavbarModule, NavbarModule,
ModalModule, ModalModule,
TableModule,
UtilitiesModule,
BadgeModule
], ],
declarations: [DeviceComponent], declarations: [DeviceComponent],
}) })

View file

@ -1,18 +1,16 @@
<c-row > <c-row>
<c-col *ngFor="let sensor of devicedata['sensors']; index as i" [sm]="6" [xl]="count_calc(devicedata)" > <c-col *ngFor="let sensor of devicedata['sensors']; index as i" [sm]="6" [xl]="count_calc(devicedata)">
<c-widget-stat-a <c-widget-stat-a class="mb-2" [color]="colors[i]" [title]="sensor">
class="mb-2"
[color]="colors[i]"
[title]="sensor"
>
<ng-template cTemplateId="widgetValueTemplate" ngPreserveWhitespaces> <ng-template cTemplateId="widgetValueTemplate" ngPreserveWhitespaces>
{{show_number(sensor,devicedata)}} {{show_number(sensor,devicedata)}}
</ng-template> </ng-template>
<ng-template cTemplateId="widgetChartTemplate"> <ng-template cTemplateId="widgetChartTemplate">
<c-chart [data]="devicedata[sensor]" [options]="(sensor=='rxp/txp-total') ? options[4] :options[2]" class="mt-3 mx-3" height="70" [type]="(sensor=='rxp/txp-total') ? 'bar' :'line'"></c-chart> <c-chart [data]="devicedata[sensor]" [options]="(check_options(sensor)) ? options[4] :options[2]"
<div [innerHTML]='show_date(devicedata[sensor]["labels"][devicedata[sensor]["datasets"][0]["data"].length-1])' class="fs-6 fw-normal" style=" class="mt-3 mx-3" height="70" [type]="(check_options(sensor)) ? 'bar' :'line'"></c-chart>
<div [innerHTML]='show_date(devicedata[sensor]["labels"][devicedata[sensor]["datasets"][0]["data"].length-1])'
class="fs-6 fw-normal" style="
padding: 5px; padding: 5px;
width: 200px; width: 200px;
text-align: center; text-align: center;

View file

@ -0,0 +1,3 @@
::ng-deep .fs-4.fw-semibold{
font-size: 0.8rem!important;
}

View file

@ -53,23 +53,18 @@ export class WidgetsDropdownComponent implements OnInit, AfterContentInit {
'danger', 'danger',
'warning', 'warning',
'info', 'info',
'light',
'dark', 'dark',
'primary', 'primary',
'success', 'success',
'danger', 'danger',
'warning', 'warning',
'info', 'info',
'light',
'dark', 'dark',
'primary', 'primary',
'success', 'success',
'danger', 'danger',
'warning', 'warning',
'info', 'info',
'light',
'dark',
'light',
'dark', 'dark',
'primary', 'primary',
'success', 'success',
@ -177,7 +172,6 @@ export class WidgetsDropdownComponent implements OnInit, AfterContentInit {
mynumber /= 1024; mynumber /= 1024;
unitIndex++; unitIndex++;
} }
console.dir(mynumber)
switch (unit) { switch (unit) {
case 'rx': case 'rx':
return mynumber.toFixed(3) + ' ' + units[unitIndex]; return mynumber.toFixed(3) + ' ' + units[unitIndex];
@ -190,7 +184,12 @@ export class WidgetsDropdownComponent implements OnInit, AfterContentInit {
break; break;
} }
} }
check_options(sensor:string){
if(sensor.indexOf('total')>-1)
return true;
else
return false;
}
show_number(sensor:string,data:any){ show_number(sensor:string,data:any){
if(sensor=='rxp/txp-total'){ if(sensor=='rxp/txp-total'){
let mynumber=data[sensor]["datasets"][0]["data"][data[sensor]["datasets"][0]["data"].length-1]; let mynumber=data[sensor]["datasets"][0]["data"][data[sensor]["datasets"][0]["data"].length-1];
@ -199,6 +198,13 @@ export class WidgetsDropdownComponent implements OnInit, AfterContentInit {
let res2=this.convert_bw_human(mynumber1,data[sensor]["datasets"][1]['unit']); let res2=this.convert_bw_human(mynumber1,data[sensor]["datasets"][1]['unit']);
return res1 + " / " + res2; return res1 + " / " + res2;
} }
else if(sensor=='rx/tx-total'){
let mynumber=data[sensor]["datasets"][0]["data"][data[sensor]["datasets"][0]["data"].length-1];
let mynumber1=data[sensor]["datasets"][1]["data"][data[sensor]["datasets"][1]["data"].length-1];
let res1=this.convert_bw_human(mynumber,data[sensor]["datasets"][0]['unit']);
let res2=this.convert_bw_human(mynumber1,data[sensor]["datasets"][1]['unit']);
return res1 + " / " + res2;
}
else{ else{
let mynumber=data[sensor]["datasets"][0]["data"][data[sensor]["datasets"][0]["data"].length-1]; let mynumber=data[sensor]["datasets"][0]["data"][data[sensor]["datasets"][0]["data"].length-1];
return mynumber return mynumber
@ -284,7 +290,6 @@ export class WidgetsDropdownComponent implements OnInit, AfterContentInit {
res /= 1024; res /= 1024;
unitIndex++; unitIndex++;
} }
console.dir(res)
switch (context.dataset.unit) { switch (context.dataset.unit) {
case 'rx': case 'rx':
return "rx/s :" + res.toFixed(3) + ' ' + units[unitIndex]; return "rx/s :" + res.toFixed(3) + ' ' + units[unitIndex];
@ -399,7 +404,6 @@ export class ChartSample implements AfterViewInit {
let { datasets, labels } = { ...this.data }; let { datasets, labels } = { ...this.data };
// @ts-ignore // @ts-ignore
const before = this.chartComponent?.chart?.data.datasets.length; const before = this.chartComponent?.chart?.data.datasets.length;
console.log('before', before);
// console.log('datasets, labels', datasets, labels) // console.log('datasets, labels', datasets, labels)
// @ts-ignore // @ts-ignore
// this.data = data() // this.data = data()
@ -416,7 +420,6 @@ export class ChartSample implements AfterViewInit {
// @ts-ignore // @ts-ignore
setTimeout(() => { setTimeout(() => {
const after = this.chartComponent?.chart?.data.datasets.length; const after = this.chartComponent?.chart?.data.datasets.length;
console.log('after', after);
}); });
}, 5000); }, 5000);
} }