WIP - UISP support and breadcrumb fixes

This commit is contained in:
Herbert Wolverson
2023-06-14 14:12:19 +00:00
parent cd87182fea
commit 820cfd9644
22 changed files with 700 additions and 192 deletions

View File

@@ -1,13 +1,19 @@
use crate::web::wss::{
nodes::node_status,
queries::{
ext_device::{
send_extended_device_capacity_graph, send_extended_device_info,
send_extended_device_snr_graph,
},
omnisearch, root_heat_map, send_circuit_info, send_packets_for_all_nodes,
send_packets_for_node, send_perf_for_node, send_rtt_for_all_nodes,
send_rtt_for_all_nodes_circuit, send_rtt_for_all_nodes_site, send_rtt_for_node,
send_site_info, send_site_parents, send_site_stack_map, send_throughput_for_all_nodes,
send_throughput_for_all_nodes_by_circuit, send_throughput_for_all_nodes_by_site,
send_throughput_for_node, site_heat_map, site_tree::send_site_tree,
time_period::InfluxTimePeriod, ext_device::send_extended_device_info,
send_throughput_for_node, site_heat_map,
site_tree::send_site_tree,
time_period::InfluxTimePeriod,
send_circuit_parents, send_root_parents,
},
};
use axum::{
@@ -257,6 +263,12 @@ async fn handle_socket(mut socket: WebSocket, cnn: Pool<Postgres>) {
(WasmRequest::SiteParents { site_id }, Some(credentials)) => {
send_site_parents(&cnn, wss, &credentials.license_key, site_id).await;
}
(WasmRequest::CircuitParents { circuit_id }, Some(credentials)) => {
send_circuit_parents(&cnn, wss, &credentials.license_key, circuit_id).await;
}
(WasmRequest::RootParents, Some(credentials)) => {
send_root_parents(&cnn, wss, &credentials.license_key).await;
}
(WasmRequest::Search { term }, Some(credentials)) => {
let _ = omnisearch(&cnn, wss, &credentials.license_key, term).await;
}
@@ -266,6 +278,26 @@ async fn handle_socket(mut socket: WebSocket, cnn: Pool<Postgres>) {
(WasmRequest::ExtendedDeviceInfo { circuit_id }, Some(credentials)) => {
send_extended_device_info(&cnn, wss, &credentials.license_key, circuit_id).await;
}
(WasmRequest::SignalNoiseChartExt { period, device_id }, Some(credentials)) => {
let _ = send_extended_device_snr_graph(
&cnn,
wss,
&credentials.license_key,
device_id,
InfluxTimePeriod::new(period),
)
.await;
}
(WasmRequest::DeviceCapacityChartExt { period, device_id }, Some(credentials)) => {
let _ = send_extended_device_capacity_graph(
&cnn,
wss,
&credentials.license_key,
device_id,
InfluxTimePeriod::new(period),
)
.await;
}
(_, None) => {
tracing::error!("No credentials");
}

View File

@@ -1,11 +1,13 @@
use std::collections::HashSet;
use axum::extract::ws::WebSocket;
use pgdb::sqlx::{Pool, Postgres};
use wasm_pipe_types::CircuitList;
use chrono::{DateTime, FixedOffset};
use influxdb2::{FromDataPoint, models::Query, Client};
use pgdb::{sqlx::{Pool, Postgres}, organization_cache::get_org_details};
use crate::web::wss::send_response;
use super::time_period::InfluxTimePeriod;
pub async fn send_extended_device_info(
cnn: &Pool<Postgres>,
socket: &mut WebSocket,
@@ -65,19 +67,100 @@ pub async fn send_extended_device_info(
}
}
fn from(circuit: pgdb::CircuitInfo) -> CircuitList {
CircuitList {
circuit_name: circuit.circuit_name,
device_id: circuit.device_id,
device_name: circuit.device_name,
parent_node: circuit.parent_node,
mac: circuit.mac,
download_min_mbps: circuit.download_min_mbps,
download_max_mbps: circuit.download_max_mbps,
upload_min_mbps: circuit.upload_min_mbps,
upload_max_mbps: circuit.upload_max_mbps,
comment: circuit.comment,
ip_range: circuit.ip_range,
subnet: circuit.subnet,
pub async fn send_extended_device_snr_graph(
cnn: &Pool<Postgres>,
socket: &mut WebSocket,
key: &str,
device_id: &str,
period: InfluxTimePeriod,
) -> anyhow::Result<()> {
if let Some(org) = get_org_details(cnn, key).await {
let influx_url = format!("http://{}:8086", org.influx_host);
let client = Client::new(influx_url, &org.influx_org, &org.influx_token);
let qs = format!(
"from(bucket: \"{}\")
|> {}
|> filter(fn: (r) => r[\"_measurement\"] == \"device_ext\")
|> filter(fn: (r) => r[\"organization_id\"] == \"{}\")
|> filter(fn: (r) => r[\"device_id\"] == \"{}\")
|> filter(fn: (r) => r[\"_field\"] == \"noise_floor\" or r[\"_field\"] == \"rx_signal\")
|> {}
|> yield(name: \"last\")",
org.influx_bucket, period.range(), org.key, device_id, period.aggregate_window()
);
//println!("{qs}");
let query = Query::new(qs);
let rows = client.query::<SnrRow>(Some(query)).await?;
let mut sn = Vec::new();
rows.iter().for_each(|row| {
let snr = wasm_pipe_types::SignalNoiseChartExt {
noise: row.noise_floor,
signal: row.rx_signal,
date: row.time.format("%Y-%m-%d %H:%M:%S").to_string(),
};
sn.push(snr);
});
send_response(socket, wasm_pipe_types::WasmResponse::DeviceExtSnr { data: sn, device_id: device_id.to_string() }).await;
}
Ok(())
}
#[derive(Debug, FromDataPoint, Default)]
pub struct SnrRow {
pub device_id: String,
pub noise_floor: f64,
pub rx_signal: f64,
pub time: DateTime<FixedOffset>,
}
pub async fn send_extended_device_capacity_graph(
cnn: &Pool<Postgres>,
socket: &mut WebSocket,
key: &str,
device_id: &str,
period: InfluxTimePeriod,
) -> anyhow::Result<()> {
if let Some(org) = get_org_details(cnn, key).await {
let influx_url = format!("http://{}:8086", org.influx_host);
let client = Client::new(influx_url, &org.influx_org, &org.influx_token);
let qs = format!(
"from(bucket: \"{}\")
|> {}
|> filter(fn: (r) => r[\"_measurement\"] == \"device_ext\")
|> filter(fn: (r) => r[\"organization_id\"] == \"{}\")
|> filter(fn: (r) => r[\"device_id\"] == \"{}\")
|> filter(fn: (r) => r[\"_field\"] == \"dl_capacity\" or r[\"_field\"] == \"ul_capacity\")
|> {}
|> yield(name: \"last\")",
org.influx_bucket, period.range(), org.key, device_id, period.aggregate_window()
);
//println!("{qs}");
let query = Query::new(qs);
let rows = client.query::<CapacityRow>(Some(query)).await?;
let mut sn = Vec::new();
rows.iter().for_each(|row| {
let snr = wasm_pipe_types::CapacityChartExt {
dl: row.dl_capacity,
ul: row.ul_capacity,
date: row.time.format("%Y-%m-%d %H:%M:%S").to_string(),
};
sn.push(snr);
});
send_response(socket, wasm_pipe_types::WasmResponse::DeviceExtCapacity { data: sn, device_id: device_id.to_string() }).await;
}
Ok(())
}
#[derive(Debug, FromDataPoint, Default)]
pub struct CapacityRow {
pub device_id: String,
pub dl_capacity: f64,
pub ul_capacity: f64,
pub time: DateTime<FixedOffset>,
}

View File

@@ -20,7 +20,7 @@ pub use rtt::{send_rtt_for_all_nodes, send_rtt_for_all_nodes_site, send_rtt_for_
pub use search::omnisearch;
pub use site_heat_map::{root_heat_map, site_heat_map};
pub use site_info::send_site_info;
pub use site_parents::send_site_parents;
pub use site_parents::{send_site_parents, send_circuit_parents, send_root_parents};
pub use throughput::{
send_throughput_for_all_nodes, send_throughput_for_all_nodes_by_circuit,
send_throughput_for_all_nodes_by_site, send_throughput_for_node,

View File

@@ -20,3 +20,28 @@ pub async fn send_site_parents(
tracing::error!("Error getting children: {:?}", child_result);
}
}
pub async fn send_circuit_parents(
cnn: &Pool<Postgres>,
socket: &mut WebSocket,
key: &str,
circuit_id: &str,
) {
if let Ok(parents) = pgdb::get_circuit_parent_list(cnn, key, circuit_id).await {
send_response(socket, wasm_pipe_types::WasmResponse::SiteParents { data: parents }).await;
}
}
pub async fn send_root_parents(
cnn: &Pool<Postgres>,
socket: &mut WebSocket,
key: &str,
) {
let site_name = "Root";
let child_result = pgdb::get_child_list(cnn, key, site_name).await;
if let Ok(children) = child_result {
send_response(socket, wasm_pipe_types::WasmResponse::SiteChildren { data: children }).await;
} else {
tracing::error!("Error getting children: {:?}", child_result);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -137,5 +137,47 @@ pub async fn get_child_list(
result.sort_by(|a, b| a.2.cmp(&b.2));
Ok(result)
}
pub async fn get_circuit_parent_list(
cnn: &Pool<Postgres>,
key: &str,
circuit_id: &str,
) -> Result<Vec<(String, String)>, StatsHostError> {
let mut result = Vec::new();
// Get the site name to start at
let site_name : String = sqlx::query("SELECT parent_node FROM shaped_devices WHERE key = $1 AND circuit_id= $2")
.bind(key)
.bind(circuit_id)
.fetch_one(cnn)
.await
.map_err(|e| StatsHostError::DatabaseError(e.to_string()))?
.get(0);
// Get the site index
let site_id_db = sqlx::query("SELECT index FROM site_tree WHERE key = $1 AND site_name=$2")
.bind(key)
.bind(site_name)
.fetch_one(cnn)
.await
.map_err(|e| StatsHostError::DatabaseError(e.to_string()))?;
let mut site_id: i32 = site_id_db.try_get("index").map_err(|e| StatsHostError::DatabaseError(e.to_string()))?;
// Get the parent list
while site_id != 0 {
let parent_db = sqlx::query("SELECT site_name, parent, site_type FROM site_tree WHERE key = $1 AND index=$2")
.bind(key)
.bind(site_id)
.fetch_one(cnn)
.await
.map_err(|e| StatsHostError::DatabaseError(e.to_string()))?;
let parent: String = parent_db.try_get("site_name").map_err(|e| StatsHostError::DatabaseError(e.to_string()))?;
let site_type: String = parent_db.try_get("site_type").map_err(|e| StatsHostError::DatabaseError(e.to_string()))?;
site_id = parent_db.try_get("parent").map_err(|e| StatsHostError::DatabaseError(e.to_string()))?;
result.push((site_type, parent));
}
Ok(result)
}

View File

@@ -5,7 +5,10 @@ import { Component } from '../components/component';
import { CircuitInfo } from '../components/circuit_info';
import { ThroughputCircuitChart } from '../components/throughput_circuit';
import { RttChartCircuit } from '../components/rtt_circuit';
import { request_ext_device_info } from "../../wasm/wasm_pipe";
import { request_ext_device_info, request_ext_snr_graph, request_ext_capacity_graph } from "../../wasm/wasm_pipe";
import * as echarts from 'echarts';
import { scaleNumber } from '../helpers';
import { CircuitBreadcrumbs } from '../components/circuit_breadcrumbs';
export class CircuitPage implements Page {
menu: MenuPage;
@@ -23,6 +26,7 @@ export class CircuitPage implements Page {
new CircuitInfo(this.circuitId),
new ThroughputCircuitChart(this.circuitId),
new RttChartCircuit(this.circuitId),
new CircuitBreadcrumbs(this.circuitId),
];
}
@@ -49,27 +53,160 @@ export class CircuitPage implements Page {
});
if (event.msg == "DeviceExt") {
console.log(event.DeviceExt.data);
//console.log(event.DeviceExt.data);
let div = document.getElementById("ext") as HTMLDivElement;
let html = "";
for (let i=0; i<event.DeviceExt.data.length; i++) {
let d = event.DeviceExt.data[i];
html += "<div class='row'>";
html += "<div class='col-6'>";
html += "<div class='col-4'>";
html += "<div class='card'>";
html += "<div class='card-body' style='height: 250px'>";
html += "<h4>" + d.name + "</h4>";
html += "<strong>Status</strong>: " + d.status + "<br>";
html += "<strong>Model</strong>: " + d.model + "<br>";
html += "<strong>Mode</strong>: " + d.mode + "<br>";
html += "<strong>Firmware</strong>: " + d.firmware + "<br>";
html += "</div>";
html += "<div class='col-6'>";
html += "</div>";
html += "</div>";
html += "<div class='col-4'>";
html += "<div class='card'>";
html += "<div class='card-body' id='extdev_" + d.device_id + "' style='height: 250px'>";
html += "<p>Signal/noise graph</p>";
html += "</div>";
html += "</div>";
html += "</div>";
request_ext_snr_graph(window.graphPeriod, d.device_id);
html += "<div class='col-4'>";
html += "<div class='card'>";
html += "<div class='card-body' id='extdev_cap_" + d.device_id + "' style='height: 250px'>";
html += "<p>Capacity Graph</p>";
html += "</div>";
html += "</div>";
html += "</div>";
request_ext_capacity_graph(window.graphPeriod, d.device_id);
// End row
html += "</div>";
}
div.outerHTML = html;
} else if (event.msg == "DeviceExtSnr") {
console.log(event);
let div = document.getElementById("extdev_" + event.DeviceExtSnr.device_id) as HTMLDivElement;
let sig: number[] = [];
let n: number[] = [];
let x: any[] = [];
for (let i=0; i<event.DeviceExtSnr.data.length; i++) {
let d = event.DeviceExtSnr.data[i];
sig.push(d.signal);
n.push(d.noise);
x.push(d.date);
}
let series: echarts.SeriesOption[] = [];
let signal: echarts.SeriesOption = {
name: "Signal",
type: "line",
data: sig,
symbol: 'none',
};
let noise: echarts.SeriesOption = {
name: "Noise",
type: "line",
data: n,
symbol: 'none',
};
series.push(signal);
series.push(noise);
let myChart: echarts.ECharts = echarts.init(div);
var option: echarts.EChartsOption;
myChart.setOption<echarts.EChartsOption>(
(option = {
title: { text: "Signal/Noise" },
legend: {
orient: "horizontal",
right: 10,
top: "bottom",
},
xAxis: {
type: 'category',
data: x,
},
yAxis: {
type: 'value',
name: 'dB',
},
series: series
})
);
option && myChart.setOption(option);
} else if (event.msg == "DeviceExtCapacity") {
console.log(event);
let div = document.getElementById("extdev_cap_" + event.DeviceExtCapacity.device_id) as HTMLDivElement;
let down: number[] = [];
let up: number[] = [];
let x: any[] = [];
for (let i=0; i<event.DeviceExtCapacity.data.length; i++) {
let d = event.DeviceExtCapacity.data[i];
down.push(d.dl);
up.push(d.ul);
x.push(d.date);
}
let series: echarts.SeriesOption[] = [];
let signal: echarts.SeriesOption = {
name: "Download",
type: "line",
data: down,
symbol: 'none',
};
let noise: echarts.SeriesOption = {
name: "Upload",
type: "line",
data: up,
symbol: 'none',
};
series.push(signal);
series.push(noise);
let myChart: echarts.ECharts = echarts.init(div);
var option: echarts.EChartsOption;
myChart.setOption<echarts.EChartsOption>(
(option = {
title: { text: "Estimated Capacity" },
legend: {
orient: "horizontal",
right: 10,
top: "bottom",
},
xAxis: {
type: 'category',
data: x,
},
yAxis: {
type: 'value',
name: 'Mbps',
axisLabel: {
formatter: function (val: number) {
return scaleNumber(Math.abs(val), 0);
}
}
},
series: series
})
);
option && myChart.setOption(option);
}
}
}

View File

@@ -1,4 +1,8 @@
<div class="container">
<div class="row">
<div class="col-12" id="siteName">
</div>
</div>
<div class="row">
<div class="col-6">
<div class="card">

View File

@@ -0,0 +1,33 @@
import { request_circuit_parents } from "../../wasm/wasm_pipe";
import { makeUrl } from "../helpers";
import { Component } from "./component";
export class CircuitBreadcrumbs implements Component {
circuitId: string;
constructor(siteId: string) {
this.circuitId = siteId;
}
wireup(): void {
request_circuit_parents(this.circuitId);
}
ontick(): void {
}
onmessage(event: any): void {
if (event.msg == "SiteParents") {
//console.log(event.data);
let div = document.getElementById("siteName") as HTMLDivElement;
let html = "";
let crumbs = event.SiteParents.data.reverse();
for (let i = 0; i < crumbs.length; i++) {
let url = makeUrl(crumbs[i][0], crumbs[i][1]);
html += "<a href='#" + url + "' onclick='window.router.goto(\"" + url + "\")'>" + crumbs[i][1] + "</a> | ";
}
html = html.substring(0, html.length - 3);
div.innerHTML = html;
}
}
}

View File

@@ -0,0 +1,33 @@
import { request_root_parents } from "../../wasm/wasm_pipe";
import { makeUrl } from "../helpers";
import { Component } from "./component";
export class RootBreadcrumbs implements Component {
constructor() {
}
wireup(): void {
let div = document.getElementById("siteName") as HTMLDivElement;
div.innerHTML = "Root | <select id='siteChildren'></select>";
request_root_parents();
}
ontick(): void {
}
onmessage(event: any): void {
if (event.msg == "SiteChildren") {
//console.log(event.data);
let html = "<option value=''>-- Children --</option>";
for (let i=0; i<event.SiteChildren.data.length; i++) {
html += "<option value='" + makeUrl(event.SiteChildren.data[i][0], event.SiteChildren.data[i][1]) + "'>" + event.SiteChildren.data[i][2] + "</option>";
}
let select = document.getElementById("siteChildren") as HTMLSelectElement;
select.innerHTML = html;
select.onchange = () => {
let select = document.getElementById("siteChildren") as HTMLSelectElement;
window.router.goto(select.value);
};
}
}
}

View File

@@ -18,6 +18,7 @@ export class SiteStackChart implements Component {
}
wireup(): void {
request_site_stack(window.graphPeriod, this.siteId);
}
ontick(): void {

View File

@@ -9,6 +9,7 @@ import { RttChart } from '../components/rtt_graph';
import { RttHisto } from '../components/rtt_histo';
import { RootHeat } from '../components/root_heat';
import { SiteStackChart } from '../components/site_stack';
import { RootBreadcrumbs } from '../components/root_breadcrumbs';
export class DashboardPage implements Page {
menu: MenuPage;
@@ -28,6 +29,7 @@ export class DashboardPage implements Page {
new RttHisto(),
new RootHeat(),
new SiteStackChart("root"),
new RootBreadcrumbs(),
];
}

View File

@@ -4,6 +4,10 @@
<h1>Dashboard</h1>
</div>
</div>
<div class="row">
<div class="col-12" id="siteName">
</div>
</div>
<div class="row">
<div class="col-6">
<div class="card">

View File

@@ -6,15 +6,15 @@ export function getValueFromForm(id: string): string {
return "";
}
export function scaleNumber(n: any): string {
export function scaleNumber(n: any, decimals: number = 1): string {
if (n >= 1000000000000) {
return (n / 1000000000000).toFixed(1) + "T";
return (n / 1000000000000).toFixed(decimals) + "T";
} else if (n >= 1000000000) {
return (n / 1000000000).toFixed(1) + "G";
return (n / 1000000000).toFixed(decimals) + "G";
} else if (n >= 1000000) {
return (n / 1000000).toFixed(1) + "M";
return (n / 1000000).toFixed(decimals) + "M";
} else if (n >= 1000) {
return (n / 1000).toFixed(1) + "K";
return (n / 1000).toFixed(decimals) + "K";
}
return n;
}

View File

@@ -104,6 +104,13 @@ export function request_site_info(site_id: string): void;
*/
export function request_site_parents(site_id: string): void;
/**
* @param {string} circuit_id
*/
export function request_circuit_parents(circuit_id: string): void;
/**
*/
export function request_root_parents(): void;
/**
* @param {string} term
*/
export function request_search(term: string): void;
@@ -115,6 +122,16 @@ export function request_circuit_info(circuit_id: string): void;
* @param {string} circuit_id
*/
export function request_ext_device_info(circuit_id: string): void;
/**
* @param {string} period
* @param {string} device_id
*/
export function request_ext_snr_graph(period: string, device_id: string): void;
/**
* @param {string} period
* @param {string} device_id
*/
export function request_ext_capacity_graph(period: string, device_id: string): void;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
@@ -142,9 +159,13 @@ export interface InitOutput {
readonly request_tree: (a: number, b: number) => void;
readonly request_site_info: (a: number, b: number) => void;
readonly request_site_parents: (a: number, b: number) => void;
readonly request_circuit_parents: (a: number, b: number) => void;
readonly request_root_parents: () => void;
readonly request_search: (a: number, b: number) => void;
readonly request_circuit_info: (a: number, b: number) => void;
readonly request_ext_device_info: (a: number, b: number) => void;
readonly request_ext_snr_graph: (a: number, b: number, c: number, d: number) => void;
readonly request_ext_capacity_graph: (a: number, b: number, c: number, d: number) => void;
readonly __wbindgen_malloc: (a: number) => number;
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
readonly __wbindgen_export_2: WebAssembly.Table;

View File

@@ -447,6 +447,21 @@ export function request_site_parents(site_id) {
wasm.request_site_parents(ptr0, len0);
}
/**
* @param {string} circuit_id
*/
export function request_circuit_parents(circuit_id) {
const ptr0 = passStringToWasm0(circuit_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
wasm.request_circuit_parents(ptr0, len0);
}
/**
*/
export function request_root_parents() {
wasm.request_root_parents();
}
/**
* @param {string} term
*/
@@ -474,6 +489,30 @@ export function request_ext_device_info(circuit_id) {
wasm.request_ext_device_info(ptr0, len0);
}
/**
* @param {string} period
* @param {string} device_id
*/
export function request_ext_snr_graph(period, device_id) {
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ptr1 = passStringToWasm0(device_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
wasm.request_ext_snr_graph(ptr0, len0, ptr1, len1);
}
/**
* @param {string} period
* @param {string} device_id
*/
export function request_ext_capacity_graph(period, device_id) {
const ptr0 = passStringToWasm0(period, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ptr1 = passStringToWasm0(device_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
wasm.request_ext_capacity_graph(ptr0, len0, ptr1, len1);
}
function handleError(f, args) {
try {
return f.apply(this, args);
@@ -636,11 +675,11 @@ function __wbg_get_imports() {
imports.wbg.__wbg_setonopen_6fd8b28538150568 = function(arg0, arg1) {
getObject(arg0).onopen = getObject(arg1);
};
imports.wbg.__wbindgen_closure_wrapper1798 = function(arg0, arg1, arg2) {
imports.wbg.__wbindgen_closure_wrapper1901 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_12);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper1799 = function(arg0, arg1, arg2) {
imports.wbg.__wbindgen_closure_wrapper1902 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 70, __wbg_adapter_12);
return addHeapObject(ret);
};

View File

@@ -23,9 +23,13 @@ export function request_site_heat(a: number, b: number, c: number, d: number): v
export function request_tree(a: number, b: number): void;
export function request_site_info(a: number, b: number): void;
export function request_site_parents(a: number, b: number): void;
export function request_circuit_parents(a: number, b: number): void;
export function request_root_parents(): void;
export function request_search(a: number, b: number): void;
export function request_circuit_info(a: number, b: number): void;
export function request_ext_device_info(a: number, b: number): void;
export function request_ext_snr_graph(a: number, b: number, c: number, d: number): void;
export function request_ext_capacity_graph(a: number, b: number, c: number, d: number): void;
export function __wbindgen_malloc(a: number): number;
export function __wbindgen_realloc(a: number, b: number, c: number): number;
export const __wbindgen_export_2: WebAssembly.Table;

View File

@@ -213,6 +213,16 @@ pub fn request_site_parents(site_id: String) {
send_message(WasmRequest::SiteParents { site_id });
}
#[wasm_bindgen]
pub fn request_circuit_parents(circuit_id: String) {
send_message(WasmRequest::CircuitParents { circuit_id });
}
#[wasm_bindgen]
pub fn request_root_parents() {
send_message(WasmRequest::RootParents);
}
#[wasm_bindgen]
pub fn request_search(term: String) {
send_message(WasmRequest::Search { term });
@@ -226,4 +236,14 @@ pub fn request_circuit_info(circuit_id: String) {
#[wasm_bindgen]
pub fn request_ext_device_info(circuit_id: String) {
send_message(WasmRequest::ExtendedDeviceInfo { circuit_id });
}
#[wasm_bindgen]
pub fn request_ext_snr_graph(period: String, device_id: String) {
send_message(WasmRequest::SignalNoiseChartExt { period, device_id });
}
#[wasm_bindgen]
pub fn request_ext_capacity_graph(period: String, device_id: String) {
send_message(WasmRequest::DeviceCapacityChartExt { period, device_id });
}

View File

@@ -24,9 +24,13 @@ pub enum WasmRequest {
Tree { parent: String },
SiteInfo { site_id: String },
SiteParents { site_id: String },
CircuitParents { circuit_id: String },
RootParents,
Search { term: String },
CircuitInfo { circuit_id: String },
ExtendedDeviceInfo { circuit_id: String },
SignalNoiseChartExt { period: String, device_id: String },
DeviceCapacityChartExt { period: String, device_id: String },
}
#[derive(Serialize, Deserialize, Debug)]
@@ -52,6 +56,8 @@ pub enum WasmResponse {
SearchResult { hits: Vec<SearchResult> },
CircuitInfo { data: Vec<CircuitList> },
DeviceExt { data: Vec<ExtendedDeviceInfo> },
DeviceExtSnr { data: Vec<SignalNoiseChartExt>, device_id: String },
DeviceExtCapacity { data: Vec<CapacityChartExt>, device_id: String },
}
#[derive(Serialize, Deserialize, Debug)]
@@ -186,4 +192,18 @@ pub struct ExtendedDeviceInterface {
pub status: String,
pub speed: String,
pub ip_list: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct SignalNoiseChartExt {
pub date: String,
pub signal: f64,
pub noise: f64,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CapacityChartExt {
pub date: String,
pub dl: f64,
pub ul: f64,
}