feat(frontend): cwmp and usp device resources

This commit is contained in:
leandrofars 2024-09-05 11:31:38 -03:00
parent e2160fee15
commit 061456957c
9 changed files with 174 additions and 1006 deletions

View File

@ -0,0 +1,13 @@
import { styled } from '@mui/material/styles';
export const VisuallyHiddenInput = styled('input')({
clip: 'rect(0 0 0 0)',
clipPath: 'inset(50%)',
height: 1,
overflow: 'hidden',
position: 'absolute',
bottom: 0,
left: 0,
whiteSpace: 'nowrap',
width: 1,
});

View File

@ -172,7 +172,8 @@ const Page = () => {
} }
const getDeviceProtocol = (order) => { const getDeviceProtocol = (order) => {
if (order.Cwmp != null) { console.log("order:", order)
if (order.Cwmp == 2) {
return "cwmp" return "cwmp"
} else { } else {
return "usp" return "usp"

View File

@ -13,15 +13,12 @@ import { DevicesRPC } from 'src/sections/devices/cwmp/devices-rpc';
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon'; import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
import MagnifyingGlassIcon from '@heroicons/react/24/solid/MagnifyingGlassIcon'; import MagnifyingGlassIcon from '@heroicons/react/24/solid/MagnifyingGlassIcon';
import WifiIcon from '@heroicons/react/24/solid/WifiIcon'; import WifiIcon from '@heroicons/react/24/solid/WifiIcon';
import WrenchScrewDriverIcon from '@heroicons/react/24/solid/WrenchScrewdriverIcon'; import ServerStackIcon from '@heroicons/react/24/outline/ServerStackIcon';
import SignalIcon from '@heroicons/react/24/solid/SignalIcon'; import SignalIcon from '@heroicons/react/24/solid/SignalIcon';
import DevicePhoneMobile from '@heroicons/react/24/solid/DevicePhoneMobileIcon'; import DevicePhoneMobile from '@heroicons/react/24/solid/DevicePhoneMobileIcon';
import { useEffect, useState } from 'react'; import WrenchScrewDriverIcon from '@heroicons/react/24/outline/WrenchScrewdriverIcon';
import CommandLineIcon from '@heroicons/react/24/outline/CommandLineIcon';
import { DevicesWiFi } from 'src/sections/devices/cwmp/devices-wifi'; import { DevicesWiFi } from 'src/sections/devices/cwmp/devices-wifi';
import { DevicesDiagnostic } from 'src/sections/devices/cwmp/devices-diagnostic';
import { SiteSurvey } from 'src/sections/devices/cwmp/site-survey';
import { ConnectedDevices } from 'src/sections/devices/cwmp/connecteddevices';
import InformactionCircleIcon from '@heroicons/react/24/outline/InformationCircleIcon';
const Page = () => { const Page = () => {
@ -29,7 +26,6 @@ const Page = () => {
const deviceID = router.query.id[0] const deviceID = router.query.id[0]
const section = router.query.id[1] const section = router.query.id[1]
const enterpriseVersion = process.env.NEXT_PUBLIC_ENTERPRISE_VERSION === "true" ? true : false;
const sectionHandler = () => { const sectionHandler = () => {
switch(section){ switch(section){
@ -37,20 +33,10 @@ const Page = () => {
return <DevicesRPC/> return <DevicesRPC/>
case "wifi": case "wifi":
return <DevicesWiFi/> return <DevicesWiFi/>
case "diagnostic":
return <DevicesDiagnostic/>
case "connected-devices":
return <ConnectedDevices/>
case "site-survey":
return <SiteSurvey/>
default: default:
return <p>Hello World</p> router.push(`/devices/cwmp/${deviceID}/wifi`)
} }
} }
useEffect(()=>{
console.log("deviceid:",deviceID)
})
return( return(
<> <>
@ -98,23 +84,36 @@ const Page = () => {
label="Site Survey" label="Site Survey"
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/site-survey`)}} onClick={()=>{router.push(`/devices/cwmp/${deviceID}/site-survey`)}}
value={"site-survey"} value={"site-survey"}
disabled={!enterpriseVersion}/> disabled={true}/>
<Tab <Tab
icon={<SvgIcon><DevicePhoneMobile/></SvgIcon>} icon={<SvgIcon><DevicePhoneMobile/></SvgIcon>}
iconPosition={"end"} iconPosition={"end"}
label="Connected Devices" label="Connected Devices"
disabled={true}
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/connected-devices`)}} onClick={()=>{router.push(`/devices/cwmp/${deviceID}/connected-devices`)}}
value={"connected-devices"} value={"connected-devices"}
disabled={!enterpriseVersion}
/> />
{/* <Tab value={"discovery"} onClick={()=>{router.push(`/devices/cwmp/${deviceID}/discovery`)}} icon={<SvgIcon><MagnifyingGlassIcon/></SvgIcon>} iconPosition={"end"} label="Discover Parameters" /> */}
<Tab <Tab
icon={<SvgIcon><WrenchScrewDriverIcon/></SvgIcon>} icon={<SvgIcon><WrenchScrewDriverIcon/></SvgIcon>}
iconPosition={"end"} iconPosition={"end"}
label="Diagnostic" label="Diagnostic"
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/diagnostic`)}} onClick={()=>{router.push(`/devices/cwmp/${deviceID}/diagnostic`)}}
value={"diagnostic"} value={"diagnostic"}
disabled={!enterpriseVersion}/> disabled={true}/>
<Tab
icon={<SvgIcon><ServerStackIcon/></SvgIcon>}
iconPosition={"end"}
label="Ports"
onClick={()=>{router.push(`/devices/usp/${deviceID}/ports`)}}
disabled={true}
value={"ports"} />
<Tab
icon={<SvgIcon><CommandLineIcon/></SvgIcon>}
iconPosition={"end"}
label="Actions"
onClick={()=>{router.push(`/devices/usp/${deviceID}/actions`)}}
disabled={true}
value={"actions"} />
<Tab <Tab
value={"msg"} value={"msg"}
onClick={()=>{router.push(`/devices/cwmp/${deviceID}/msg`)}} onClick={()=>{router.push(`/devices/cwmp/${deviceID}/msg`)}}

View File

@ -2,22 +2,32 @@ import Head from 'next/head';
import { Box, Stack, Typography, Container, Unstable_Grid2 as Grid, import { Box, Stack, Typography, Container, Unstable_Grid2 as Grid,
Tab, Tab,
Tabs, Tabs,
SvgIcon } from '@mui/material'; SvgIcon,
Breadcrumbs,
Link,
CircularProgress,
Tooltip} from '@mui/material';
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout'; import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { DevicesRPC } from 'src/sections/devices/usp/devices-rpc'; import { DevicesRPC } from 'src/sections/devices/usp/devices-rpc';
import { DevicesDiscovery } from 'src/sections/devices/usp/devices-discovery'; import { DevicesDiscovery } from 'src/sections/devices/usp/devices-discovery';
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon'; import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
import MagnifyingGlassIcon from '@heroicons/react/24/solid/MagnifyingGlassIcon'; import MagnifyingGlassIcon from '@heroicons/react/24/solid/MagnifyingGlassIcon';
import WifiIcon from '@heroicons/react/24/solid/WifiIcon'; import WifiIcon from '@heroicons/react/24/outline/WifiIcon';
import { useEffect, useState } from 'react'; import ServerStackIcon from '@heroicons/react/24/outline/ServerStackIcon';
import { DevicesWiFi } from 'src/sections/devices/usp/devices-wifi'; import { useState } from 'react';
import SignalIcon from '@heroicons/react/24/solid/SignalIcon';
import DevicePhoneMobile from '@heroicons/react/24/solid/DevicePhoneMobileIcon';
import WrenchScrewDriverIcon from '@heroicons/react/24/outline/WrenchScrewdriverIcon';
import CommandLineIcon from '@heroicons/react/24/outline/CommandLineIcon';
const Page = () => { const Page = () => {
const router = useRouter() const router = useRouter()
const deviceID = router.query.id[0] const deviceID = router.query.id[0]
const section = router.query.id[1] const section = router.query.id[1]
const [loading, setLoading] = useState(true)
const sectionHandler = () => { const sectionHandler = () => {
switch(section){ switch(section){
@ -25,16 +35,10 @@ const Page = () => {
return <DevicesRPC/> return <DevicesRPC/>
case "discovery": case "discovery":
return <DevicesDiscovery/> return <DevicesDiscovery/>
// case "wifi":
// return <DevicesWiFi/>
default: default:
return <p>Hello World</p> router.push(`/devices/usp/${deviceID}/discovery`)
} }
} }
useEffect(()=>{
console.log("deviceid:",deviceID)
})
return( return(
<> <>
@ -52,18 +56,84 @@ const Page = () => {
> >
<Container maxWidth="lg" > <Container maxWidth="lg" >
<Stack spacing={3} > <Stack spacing={3} >
<Breadcrumbs separator="" aria-label="breadcrumb" sx={{md: 40, mr: 20}}>
{[<Link underline="hover" key="1" color="inherit" href="/devices">
Devices
</Link>,
<Link
underline="none"
key="2"
color="inherit"
hre={`/devices/${deviceID}`}
>
{deviceID}
</Link>]}
</Breadcrumbs>
<Box sx={{ <Box sx={{
display:'flex', display:'flex',
justifyContent:'center' justifyContent:'center'
}} }}
mb={3}> mb={3}>
<Tabs value={router.query.id[1]} aria-label="icon label tabs example"> <Tabs value={router.query.id[1]} aria-label="icon label tabs example">
{/* <Tab icon={<SvgIcon><WifiIcon/></SvgIcon>} iconPosition={"end"} label="Wi-Fi" onClick={()=>{router.push(`/devices/usp/${deviceID}/wifi`)}} value={"wifi"}/> */} <Tab
<Tab value={"discovery"} onClick={()=>{router.push(`/devices/usp/${deviceID}/discovery`)}} icon={<SvgIcon><MagnifyingGlassIcon/></SvgIcon>} iconPosition={"end"} label="Discover Parameters" /> icon={<SvgIcon><WifiIcon/></SvgIcon>}
<Tab value={"msg"} onClick={()=>{router.push(`/devices/usp/${deviceID}/msg`)}} icon={<SvgIcon><EnvelopeIcon/></SvgIcon>} iconPosition={"end"} label="Remote Messages" /> iconPosition={"end"}
label="Wi-Fi"
onClick={()=>{router.push(`/devices/usp/${deviceID}/wifi`)}}
disabled={true}
value={"wifi"}/>
<Tab
icon={<SvgIcon><SignalIcon/></SvgIcon>}
iconPosition={"end"}
label="Site Survey"
style={{opacity:"0.5"}}
onClick={()=>{router.push(`/devices/usp/${deviceID}/site-survey`)}}
disabled={true}
value={"site-survey"}
/>
<Tab
icon={<SvgIcon><DevicePhoneMobile/></SvgIcon>}
iconPosition={"end"}
label="Connected Devices"
onClick={()=>{router.push(`/devices/usp/${deviceID}/connected-devices`)}}
disabled={true}
value={"connected-devices"}
/>
<Tab
icon={<SvgIcon><WrenchScrewDriverIcon/></SvgIcon>}
iconPosition={"end"}
label="Diagnostic"
onClick={()=>{router.push(`/devices/usp/${deviceID}/diagnostic`)}}
disabled={true}
value={"diagnostic"} />
<Tab
icon={<SvgIcon><ServerStackIcon/></SvgIcon>}
iconPosition={"end"}
label="Ports"
onClick={()=>{router.push(`/devices/usp/${deviceID}/ports`)}}
disabled={true}
value={"ports"} />
<Tab
icon={<SvgIcon><CommandLineIcon/></SvgIcon>}
iconPosition={"end"}
label="Actions"
onClick={()=>{router.push(`/devices/usp/${deviceID}/actions`)}}
disabled={true}
value={"actions"} />
<Tab
value={"discovery"}
onClick={()=>{router.push(`/devices/usp/${deviceID}/discovery`)}}
icon={<SvgIcon><MagnifyingGlassIcon/></SvgIcon>}
iconPosition={"end"}
label="Discover Parameters" />
<Tab
value={"msg"}
onClick={()=>{router.push(`/devices/usp/${deviceID}/msg`)}}
icon={<SvgIcon><EnvelopeIcon/></SvgIcon>}
iconPosition={"end"}
label="Remote Messages" />
</Tabs> </Tabs>
</Box> </Box>
{ {
sectionHandler() sectionHandler()
} }

View File

@ -1,148 +0,0 @@
import React, { useEffect, useState } from "react";
import { Card, CardActions, CardContent, CardHeader, CircularProgress, Divider, Grid, InputLabel, MenuItem, Select, SvgIcon, Tooltip, Typography } from "@mui/material";
import CpuChipIcon from "@heroicons/react/24/solid/CpuChipIcon";
import { Stack } from "@mui/system";
import { useTheme } from "@emotion/react";
import { useRouter } from "next/router";
import { set } from "nprogress";
export const ConnectedDevices = () => {
const theme = useTheme();
const router = useRouter();
const [content, setContent] = useState(null);
const [interfaces, setInterfaces] = useState([]);
const [interfaceValue, setInterfaceValue] = useState(null);
const getConnectionState = (rssi) => {
let connectionStatus = "Signal "
if (rssi > -30) {
return connectionStatus + "Excellent"
} else if (rssi > -60) {
return connectionStatus + "Good"
} else if (rssi > -70) {
return connectionStatus + "Bad"
} else {
return connectionStatus + "Awful"
}
}
const fetchConnectedDevicesData = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", localStorage.getItem("token"));
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/connecteddevices`, requestOptions)
.then(response => {
if (response.status === 401) {
router.push("/auth/login")
}
return response.json()
})
.then(result => {
console.log("connecteddevices content", result)
let interfaces = Object.keys(result)
setInterfaces(interfaces)
setInterfaceValue(interfaces[0])
setContent(result)
})
.catch(error => console.log('error', error));
};
useEffect(() => {
fetchConnectedDevicesData();
}, [])
return (
<Stack
justifyContent="center"
alignItems={(!content || interfaces.length == 0) && "center"}
>
{content && interfaces.length > 0 ?
<Card>
<CardContent>
<Grid mb={3}>
<InputLabel> Interface </InputLabel>
<Select label="interface" variant="standard" value={interfaceValue} onChange={(e) => setInterfaceValue(e.target.value)}>
{(
interfaces.map((item, index) => (
<MenuItem key={index} value={item}>
{item}
</MenuItem>
))
)}
</Select>
</Grid>
{
content[interfaceValue].map((property, index) => (
<Card key={index}>
<CardContent>
<Grid container justifyContent={"center"}>
<Stack direction="row" spacing={5}>
<Stack justifyItems={"center"} direction={"row"} mt={2}>
<Tooltip title={property.active ? "Online" : "Offline"}>
<SvgIcon>
<CpuChipIcon color={property.active ? theme.palette.success.main : theme.palette.error.main}></CpuChipIcon>
</SvgIcon>
</Tooltip>
<Typography ml={"10px"}>
{property.hostname}
</Typography>
</Stack>
<Divider orientation="vertical" />
<Stack spacing={2}>
<Typography>
IP address: {property.ip_adress}
</Typography>
<Typography>
MAC: {property.mac}
</Typography>
</Stack>
<Stack spacing={2}>
<Typography>
Source: {property.adress_source}
</Typography>
<Tooltip title={getConnectionState(property.rssi)}>
<Typography display={"flex"} color={() => {
let rssi = property.rssi
if(rssi == 0){
return theme.palette.neutral[900]
} else if (rssi > -30) {
return theme.palette.success.main
} else if (rssi > -60) {
return theme.palette.success.main
} else if (rssi > -70) {
return theme.palette.warning.main
} else {
return theme.palette.error.main
}
}}>
<Typography color={theme.palette.neutral[900]} sx={{pr:"5px"}}>
RSSI:
</Typography>
{property.rssi} dbm
</Typography>
</Tooltip>
</Stack>
</Stack>
</Grid>
</CardContent>
</Card>
))
}
</CardContent>
</Card> : (
content ? <Typography> No connected devices found </Typography> : <CircularProgress />
)}
</Stack>
)
}

View File

@ -1,239 +0,0 @@
import { use, useCallback, useEffect, useState } from 'react';
import {
Button,
Card,
CardActions,
CardContent,
CardHeader,
Stack,
TextField,
SvgIcon,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Box,
IconButton,
Input,
Typography,
DialogContentText
} from '@mui/material';
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
import Check from '@heroicons/react/24/outline/CheckIcon';
import CircularProgress from '@mui/material/CircularProgress';
import Backdrop from '@mui/material/Backdrop';
import { useRouter } from 'next/router';
import ArrowsUpDownIcon from '@heroicons/react/24/solid/ArrowsUpDownIcon';
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
export const DevicesDiagnostic = () => {
const router = useRouter()
const [content, setContent] = useState(null)
const [applyPing, setApplyPing] = useState(false)
const [pingResponse, setPingResponse] = useState(null)
const [progress, setProgress] = useState(0);
//TODO: fixme
// useEffect(()=>{
// let timeout = content?.number_of_repetitions.value * content?.timeout.value
// if (timeout <= 0) return;
// const increment = 100 / timeout ;// Calculate increment based on the timeout
// const interval = setInterval(() => {
// setProgress((prevProgress) => (
// prevProgress >= 100 ? 0 : prevProgress + increment
// ));
// }, 1000);
// return () => {
// clearInterval(interval);
// };
// },[content])
const fetchPingData = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", localStorage.getItem("token"));
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/ping`, requestOptions)
.then(response => {
if (response.status === 401) {
router.push("/auth/login")
}
return response.json()
})
.then(result => {
console.log("ping content", result)
setContent(result)
})
.catch(error => console.log('error', error));
};
useEffect(()=>{
fetchPingData()
},[])
const handlePing = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", localStorage.getItem("token"));
var requestOptions = {
method: 'PUT',
headers: myHeaders,
redirect: 'follow',
body: JSON.stringify(content)
};
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/ping`, requestOptions)
.then(response => {
if (response.status === 401) {
router.push("/auth/login")
}
return response.json()
})
.then(result => {
console.log("ping content", result)
setProgress(100)
setApplyPing(false)
setPingResponse(result)
})
.catch(error => console.log('error', error));
}
return ( content &&
<div>
<Stack
direction="row"
spacing={2}
justifyContent="center"
alignItems="center"
>
<Card sx={{minWidth:"500px"}}>
<CardHeader
title="Ping"
avatar={
<SvgIcon>
<ArrowsUpDownIcon/>
</SvgIcon>
}
/>
<CardContent>
<Stack spacing={3}>
<TextField
fullWidth
label="Host"
name="host"
type="text"
value={content.host.value}
onChange={(e) => setContent({...content, host: {value: e.target.value}})}
/>
<TextField
fullWidth
label="Count"
name="count"
type="number"
value={content.number_of_repetitions.value}
onChange={(e) => setContent({...content, number_of_repetitions: {value: e.target.valueAsNumber}})}
/>
<TextField
fullWidth
label="Timeout"
name="timeout"
type="number"
value={content.timeout.value}
onChange={(e) => setContent({...content, timeout: {value: e.target.valueAsNumber}})}
/>
</Stack>
</CardContent>
<CardActions sx={{ justifyContent: 'flex-end' }}>
<Button
variant="contained"
color="primary"
endIcon={
<SvgIcon>
<PaperAirplane/>
</SvgIcon>
}
onClick={()=>{
setApplyPing(true)
handlePing()
}}
>
Ping
</Button>
</CardActions>
</Card>
</Stack>
{applyPing &&
<Backdrop
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
open={applyPing}
>
<CircularProgress /*variant="determinate" value={progress}*/ color="inherit"/>
</Backdrop>
}{ pingResponse &&
<Dialog open={!applyPing && pingResponse}>
<DialogTitle>
<Box display="flex" alignItems="center">
<Box flexGrow={1} >Ping Result</Box>
<Box>
<IconButton >
<SvgIcon
onClick={()=>{
setPingResponse(null)
}}
>
<XMarkIcon />
</SvgIcon>
</IconButton>
</Box>
</Box>
</DialogTitle>
<DialogContent>
<DialogContentText>
<Stack spacing={2}>
{!pingResponse.failure_count && !pingResponse.success_count ?
<Typography sx={{display:"flex", justifyContent:"center"}}>
Error: {pingResponse}
</Typography>:<div>
<Stack spacing={2}>
<Typography sx={{display:"flex", justifyContent:"center", fontWeight:'fontWeightMedium'}}>
Ping Statistics for {content.host.value}
</Typography>
<Typography sx={{display:"flex", justifyContent:"center"}}>
Failure Count: {pingResponse.failure_count} | Success Count: {pingResponse.success_count}
</Typography>
<Typography>
Average Time: {pingResponse.average_rtt}s | Minimum Time: {pingResponse.minimum_rtt}s | Maximum Time: {pingResponse.maximum_rtt}s
</Typography></Stack></div>
}
</Stack>
</DialogContentText>
</DialogContent>
<DialogActions>
<Button
variant="contained"
color="primary"
onClick={()=>{
setPingResponse(null)
}}
>
OK
</Button>
</DialogActions>
</Dialog>}
</div>
)
};

View File

@ -1,441 +0,0 @@
import {
Button,
Card,
CardActions,
CardContent,
CardHeader,
Divider,
SvgIcon,
FormControl,
FormLabel,
Radio,
RadioGroup,
Grid,
FormControlLabel,
Box,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
TableContainer,
CircularProgress,
ToggleButton,
ToggleButtonGroup
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { Chart } from 'src/components/chart';
import ChartBarSquareIcon from '@heroicons/react/24/outline/ChartBarSquareIcon';
import ListBulletIcon from '@heroicons/react/24/outline/ListBulletIcon';
import { useRouter } from 'next/router';
import { Stack } from '@mui/system';
import { useEffect, useState } from 'react';
export const SiteSurvey = (props) => {
// const getMaxChannel = () => {
// if (frequency == "2.4GHz") {
// return 13;
// } else {
// return 128;
// }
// }
// const geMinChannel = () => {
// if (frequency == "2.4GHz") {
// return 0;
// } else {
// return 36;
// }
// }
// const getChannelSpacing = () => {
// if (frequency == "2.4GHz") {
// return 1;
// } else {
// return 4;
// }
// }
// const getChannelAmount = () => {
// if (frequency == "2.4GHz") {
// return 13;
// } else {
// return 20;
// }
// }
const getCategories = () => {
}
const router = useRouter();
const [frequency, setFrequency] = useState("2.4GHz");
const [view, setView] = useState("chart");
const [content, setContent] = useState(null);
const getSeries = () => {
let series = []
content[frequency].map((network) => {
let data = []
if (frequency == "2.4GHz") {
if (Number(network.bandwidth) == 20) {
data.push({"x": Number(network.channel) -2, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +2, "y": -100})
}
if (Number(network.bandwidth) == 40) {
data.push({"x": Number(network.channel) -4, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +4, "y": -100})
}
}else {
if (Number(network.bandwidth) == 20) {
data.push({"x": Number(network.channel) -4, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +4, "y": -100})
}
if (Number(network.bandwidth) == 40) {
data.push({"x": Number(network.channel) -8, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +8, "y": -100})
}
if (Number(network.bandwidth) == 80) {
data.push({"x": Number(network.channel) -16, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +16, "y": -100})
}
if (Number(network.bandwidth) == 160) {
data.push({"x": Number(network.channel) -32, "y": -100})
data.push({"x": Number(network.channel), "y": Number(network.signal_level)})
data.push({"x": Number(network.channel) +32, "y": -100})
}
}
let ssid = network.ssid
if ( ssid == "") {
ssid = " "
}
return series.push({
name: ssid,
data: data
})
})
return series;
}
const useChartOptions = () => {
const theme = useTheme();
return {
chart: {
background: 'transparent',
stacked: false,
toolbar: {
show: true
},
zoom: {
enabled: false
},
},
title: {
text: 'Site Survey Results',
},
// markers: {
// size: 5,
// hover: {
// size: 9
// }
// },
colors: [
theme.palette.graphics.dark,
theme.palette.warning.main,
theme.palette.graphics.darkest,
theme.palette.graphics.main,
theme.palette.info.light,
theme.palette.graphics.lightest,
theme.palette.primary.main,
theme.palette.graphics.light,
theme.palette.error.light,
theme.palette.error.dark
],
dataLabels: {
enabled: false
},
grid: {
//borderColor: theme.palette.divider,
strokeDashArray: 2,
xaxis: {
lines: {
show: true
}
},
yaxis: {
lines: {
show: true
},
},
},
legend: {
show: true,
showForSingleSeries: true,
},
plotOptions: {
area: {
fillTo: 'end',
}
},
stroke: {
show: true,
curve: 'smooth',
lineCap: 'round',
},
theme: {
mode: theme.palette.mode
},
yaxis: {
min: -100,
max: 0,
labels: {
formatter: function (value) {
return value + ' dBm';
},
//offsetY: -10,
style: {
//colors: theme.palette.text.secondary
}
},
},
// annotations: {
// xaxis: [
// {
// x: 9,
// x2: 10,
// borderColor: '#0b54ff',
// label: {
// style: {
// color: 'black',
// },
// text: 'Channel 10',
// offsetX: 45,
// borderColor: 'transparent',
// style: {
// background: 'transparent',
// color: theme.palette.text.secondary,
// fontSize: '17px',
// },
// }
// }
// ]
// },
// annotations: {
// points: [{
// x: 9,
// y: -5,
// label: {
// borderColor: '#775DD0',
// offsetY: 0,
// style: {
// color: '#fff',
// background: '#775DD0',
// },
// rotate: -45,
// text: 'Bananas are good',
// }
// }]
// },
xaxis: {
// tickPlacement: 'on',
// tickAmount: getChannelAmount(),
tickPlacement: 'on',
labels: {
show: true,
style: {
//colors: theme.palette.text.secondary
},
trim: true,
},
// max: getMaxChannel(),
// min: geMinChannel(),
// stepSize: getChannelSpacing(),
//type: 'category',
//categories: [getCategories()],
type: 'numeric',
decimalsInFloat: 0,
},
tooltip: {
x: {
show: true,
formatter: (seriesName) => "Channel "+ seriesName,
},
followCursor: false,
intersect: false,
shared: true,
enabled: true,
onDatasetHover: {
highlightDataSeries: true,
}
}
};
};
const chartOptions = useChartOptions();
const fetchSiteSurveyData = async () => {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Authorization", localStorage.getItem("token"));
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/sitesurvey`, requestOptions)
.then(response => {
if (response.status === 401) {
router.push("/auth/login")
}
return response.json()
})
.then(result => {
console.log("sitesurvey content", result)
setContent(result)
})
.catch(error => console.log('error', error));
};
useEffect(() => {
fetchSiteSurveyData();
},[])
return (
<Stack
justifyContent="center"
alignItems={!content &&"center"}
>
{content ?
<Grid spacing={1}>
<Grid container>
<Card>
<ToggleButtonGroup
value={view}
exclusive
onChange={(e, value) => {
setView(value)
}}
>
<ToggleButton
size="small"
value="chart"
>
<SvgIcon>
<ChartBarSquareIcon />
</SvgIcon>
</ToggleButton>
<ToggleButton
size="small"
value="list"
>
<SvgIcon>
<ListBulletIcon />
</SvgIcon>
</ToggleButton>
</ToggleButtonGroup>
</Card>
</Grid>
<Box display="flex"
justifyContent="center"
alignItems="center"
marginBottom={3}
>
<FormControl>
<RadioGroup
aria-labelledby="demo-controlled-radio-buttons-group"
name="controlled-radio-buttons-group"
value={frequency}
onChange={(e) => {
setFrequency(e.target.value)
}}
>
<Grid container>
<FormControlLabel value="2.4GHz" control={<Radio />} label="2.4GHz" />
<FormControlLabel value="5GHz" control={<Radio />} label="5GHz" />
</Grid>
</RadioGroup>
</FormControl>
</Box>
{view == "list" && <Card sx={{ height: '100%' }}>
<Box sx={{ minWidth: 800, }}>
<TableContainer sx={{ maxHeight: 600 }}>
<Table exportButton={true}>
<TableHead>
<TableRow>
<TableCell align="center">
SSID
</TableCell>
<TableCell>
Channel
</TableCell>
<TableCell>
BandWidth
</TableCell>
<TableCell>
Standard
</TableCell>
<TableCell>
Signal Level
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{content[frequency] && content[frequency].map((c) => {
return (
<TableRow
hover
key={c.ssid + c.signal_level}
>
<TableCell align="center">
{c.ssid}
</TableCell>
<TableCell>
{c.channel}
</TableCell>
<TableCell>
{c.bandwidth}MHz
</TableCell>
<TableCell>
{c.standard}
</TableCell>
<TableCell>
{c.signal_level} dbm
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</Box>
</Card>}
{view == "chart" && <Card>
<CardContent>
<Chart
height={500}
options={chartOptions}
series={getSeries()}
type="area"
width="100%"
/>
</CardContent>
</Card>}
</Grid>: <CircularProgress></CircularProgress>}
</Stack>
);
};

View File

@ -464,8 +464,53 @@ const [inputArgsValue, setInputArgsValue] = useState({})
// } // }
const initialize = async (raw) => { const initialize = async (raw) => {
let content = await getDeviceParameters(raw) // let content = await getDeviceParameters(raw)
setDeviceParameters(content) // console.log("get device parameters content:", content)
// let parametersToFetch = () => {
// let paramsToFetch = []
// for (let i =0; i < supportedParams.length ;i++){
// let supported_obj_path = content.req_obj_results[0].supported_objs[0].supported_obj_path.replaceAll("{i}","*")
// let param = supportedParams[i]
// paramsToFetch.push(supported_obj_path+param.param_name)
// paramsInfo[param.param_name] = {
// "value_change":param["value_change"],
// "value_type":param["value_type"],
// "access": param["access"],
// "value": "-",
// }
// }
// if (supportedCommands === undefined){
// return paramsToFetch
// }
// for(let i =0; i < supportedCommands.length; i++){
// let command = supportedCommands[i]
// commandsInfo[command.command_name] = {
// "type":command["command_type"]
// }
// }
// return paramsToFetch
// }
// const fetchparameters = parametersToFetch()
// console.log("parameters to fetch: ", fetchparameters)
// raw = JSON.stringify({
// "param_paths": fetchparameters,
// "max_depth": 1
// })
// let values = await getDeviceParametersValue(raw),
updateDeviceParameters("Device.")
// setDeviceParametersValue(values)
// setDeviceParameters(content)
//initDeviceCommands(content) //initDeviceCommands(content)
} }
@ -786,10 +831,10 @@ const getDeviceParameterInstances = async (raw) =>{
} }
throw new Error('Please check your email and password'); throw new Error('Please check your email and password');
}else if (result.status === 401){ }else if (result.status === 401){
router.push("/auth/login") router.push("/auth/login")
}else{ }else{
return result.json() return result.json()
} }
} }
@ -1205,12 +1250,12 @@ const getDeviceParameterInstances = async (raw) =>{
}} }}
open={showLoading} open={showLoading}
> >
<CircularProgress color="inherit" /> <CircularProgress />
</Backdrop> </Backdrop>
</Card> </Card>
: :
<Box sx={{display:'flex',justifyContent:'center'}}> <Box sx={{display:'flex',justifyContent:'center'}}>
<CircularProgress color="inherit" /> <CircularProgress />
</Box> </Box>
) )
}; };

View File

@ -1,132 +0,0 @@
import { useCallback, useEffect, useState } from 'react';
import {
Button,
Card,
CardActions,
CardContent,
CardHeader,
Divider,
Stack,
TextField,
InputLabel,
MenuItem,
Select,
FormControl,
SvgIcon,
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions,
Box,
IconButton,
Icon,
Checkbox,
FormControlLabel
} from '@mui/material';
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
import Check from '@heroicons/react/24/outline/CheckIcon'
import CircularProgress from '@mui/material/CircularProgress';
import Backdrop from '@mui/material/Backdrop';
import { useRouter } from 'next/router';
import GlobeAltIcon from '@heroicons/react/24/outline/GlobeAltIcon';
export const DevicesWiFi = () => {
return (
<Stack
direction="row"
spacing={2}
justifyContent="center"
alignItems="center"
>
<Card>
<CardHeader
title="2.4GHz"
avatar={
<SvgIcon>
<GlobeAltIcon/>
</SvgIcon>
}
/>
<CardContent>
<Stack spacing={3}>
<FormControlLabel control={<Checkbox defaultChecked />} label="Enabled" />
<TextField
fullWidth
label="SSID"
value="wlan0"
variant="outlined"
/>
<TextField
fullWidth
label="Encryption"
value="WPA2-PSK"
variant="outlined"
/>
<TextField
fullWidth
label="Key"
value="password"
variant="outlined"
/>
</Stack>
</CardContent>
</Card>
<Card>
<CardHeader
title="5GHz"
avatar={
<SvgIcon>
<GlobeAltIcon/>
</SvgIcon>
}
/>
<CardContent>
<Stack spacing={4}>
<FormControlLabel control={<Checkbox defaultChecked />} label="Enabled" />
<TextField
fullWidth
label="SSID"
value="wlan0"
variant="outlined"
/>
<FormControl variant="outlined" sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-simple-select-standard-label">Security</InputLabel>
<Select
labelId="demo-simple-select-standard-label"
id="demo-simple-select-standard"
value={"WPA2-PSK"}
//onChange={handleChange}
label="Security"
>
<MenuItem value={30}>Open</MenuItem>
<MenuItem value={"WPA2-PSK"}>WPA2-PSKnp</MenuItem>
<MenuItem value={20}>WPA3</MenuItem>
</Select>
</FormControl>
<TextField
fullWidth
label="Key"
value="password"
variant="outlined"
/>
</Stack>
<CardActions sx={{display:"flex", justifyContent:"flex-end"}}>
<Button
variant="contained"
endIcon={<SvgIcon><Check /></SvgIcon>}
// onClick={}
sx={{mt:'25px', mb:'-15px'}}
>
Apply
</Button>
</CardActions>
</CardContent>
</Card>
</Stack>
);
};