feat(frontend): custom cwmp/usp messages templates

This commit is contained in:
leandrofars 2024-10-30 14:17:35 -03:00
parent 55cf6f4310
commit 0d134e1082
2 changed files with 760 additions and 308 deletions

View File

@ -19,37 +19,26 @@ import {
DialogContentText, DialogContentText,
DialogActions, DialogActions,
Box, Box,
IconButton IconButton,
Grid
} from '@mui/material'; } from '@mui/material';
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon'; import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon'; import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import Backdrop from '@mui/material/Backdrop'; import Backdrop from '@mui/material/Backdrop';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useBackendContext } from 'src/contexts/backend-context';
import DocumentArrowDown from '@heroicons/react/24/outline/DocumentArrowDownIcon';
import TrashIcon from '@heroicons/react/24/outline/TrashIcon';
import PlusCircleIcon from '@heroicons/react/24/outline/PlusCircleIcon';
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
export const DevicesRPC = () => { export const DevicesRPC = () => {
const router = useRouter() const router = useRouter()
let { httpRequest } = useBackendContext()
const [open, setOpen] = useState(false);
const [scroll, setScroll] = useState('paper');
const [answer, setAnswer] = useState(false)
const [content, setContent] = useState('')
const [age, setAge] = useState(2);
const [value, setValue] = useState(`<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<cwmp:GetParameterValues>
<ParameterNames>
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.</string>
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.</string>
</ParameterNames>
</cwmp:GetParameterValues>
</soap:Body>
</soap:Envelope>`)
var prettifyXml = function(sourceXml) var prettifyXml = function(sourceXml)
{ {
@ -75,130 +64,220 @@ var prettifyXml = function(sourceXml)
return resultXml; return resultXml;
}; };
const handleClose = () => { const [open, setOpen] = useState(false);
setOpen(false); const [scroll, setScroll] = useState('paper');
}; const [answer, setAnswer] = useState(false)
const handleOpen = () => { const [content, setContent] = useState('')
setOpen(true); const [age, setAge] = useState(6);
var myHeaders = new Headers(); const [newMessage, setNewMessage] = useState(false)
myHeaders.append("Authorization", localStorage.getItem("token")); const [message, setMessage] = useState(null)
const [currentMsg, setCurrentMsg] = useState(0)
var raw = value const [newMsgName, setNewMsgName] = useState("")
const [value, setValue] = useState()
var requestOptions = { const [saveChanges, setSaveChanges] = useState(false)
method: 'PUT', const [loadingSaveMsg, setLoadingSaveMsg] = useState(false)
headers: myHeaders, const possibleMsgs = [
body: raw, `<?xml version="1.0" encoding="UTF-8"?>
redirect: 'follow' <soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
}; <soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
var method; <cwmp:SetParameterValues>
<ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[4]">
switch(age) { <ParameterValueStruct>
case 1: <Name>InternetGatewayDevice.TraceRouteDiagnostics.Host</Name>
method="addObject" <Value>192.168.60.4</Value>
break; </ParameterValueStruct>
case 2: </ParameterList>
method="getParameterValues" <ParameterKey></ParameterKey>
break; </cwmp:SetParameterValues>
case 3: </soap:Body>
method="setParameterValues" </soap:Envelope>`,
break; `<?xml version="1.0" encoding="UTF-8"?>
case 4: <soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
method="deleteObject" <soap:Header/>
break; <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
} <cwmp:DeleteObject>
<ObjectName>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.</ObjectName>
<ParameterKey></ParameterKey>
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/cwmp/${router.query.id[0]}/${method}`, requestOptions) </cwmp:DeleteObject>
.then(response => response.text()) </soap:Body>
.then(result => { </soap:Envelope>`,
if (result.status === 401){ `<?xml version="1.0" encoding="UTF-8"?>
router.push("/auth/login")
}
setOpen(false)
setAnswer(true)
let teste = prettifyXml(result)
console.log(teste)
setContent(teste)
})
.catch(error => console.log('error', error));
};
const handleChangeRPC = (event) => {
setAge(event.target.value);
switch(event.target.value) {
case 1:
setValue(`<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/> <soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<cwmp:AddObject> <cwmp:AddObject>
<ObjectName>InternetGatewayDevice.LANDevice.</ObjectName> <ObjectName>InternetGatewayDevice.LANDevice.1.WLANConfiguration.</ObjectName>
<ParameterKey></ParameterKey> <ParameterKey></ParameterKey>
</cwmp:AddObject> </cwmp:AddObject>
</soap:Body> </soap:Body>
</soap:Envelope>`) </soap:Envelope>`,
break; `<?xml version="1.0" encoding="UTF-8"?>
case 2:
setValue(`<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<cwmp:Reboot>
<CommandKey>
007
</CommandKey>
</cwmp:Reboot>
</soap:Body>
</soap:Envelope>`,
`<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..schemaswt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/> <soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<cwmp:GetParameterValues> <cwmp:GetParameterValues>
<ParameterNames> <ParameterNames>
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.</string> <string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.</string>
<string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.</string>
<string>InternetGatewayDevice.LANDevice.2.WLANConfiguration.2.</string>
<string>InternetGatewayDevice.LANDevice.2.WLANConfiguration.1.</string>
</ParameterNames> </ParameterNames>
</cwmp:GetParameterValues> </cwmp:GetParameterValues>
</soap:Body> </soap:Body>
</soap:Envelope>`) </soap:Envelope>`,`<?xml version="1.0" encoding="UTF-8"?>
break;
case 3:
setValue(`
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/> <soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<cwmp:SetParameterValues> <cwmp:GetParameterNames>
<ParameterList soapenc:arrayType="cwmp:ParameterValueStruct[3]"> <ParameterPath>InternetGatewayDevice.</ParameterPath>
<ParameterValueStruct> <NextLevel>1</NextLevel>
<Name>InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.Enable</Name> </cwmp:GetParameterNames>
<Value>0</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.SSID</Name>
<Value>HUAWEI_TEST-2</Value>
</ParameterValueStruct>
</ParameterList>
<ParameterKey>LC1309123</ParameterKey>
</cwmp:SetParameterValues>
</soap:Body> </soap:Body>
</soap:Envelope>`) </soap:Envelope>`,
break; `<?xml version="1.0" encoding="UTF-8"?>
case 4:
setValue(`<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:cwmp="urn:dslforum-org:cwmp-1-0" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:schemaLocation="urn:dslforum-org:cwmp-1-0 ..\schemas\wt121.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header/> <soap:Header/>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<cwmp:DeleteObject> <cwmp:GetParameterAttributes>
<ObjectName>InternetGatewayDevice.LANDevice.3.</ObjectName> <ParameterNames>
<ParameterKey></ParameterKey> <string>InternetGatewayDevice.LANDevice.1.WLANConfiguration.</string>
</cwmp:DeleteObject> </ParameterNames>
</cwmp:GetParameterAttributes>
</soap:Body> </soap:Body>
</soap:Envelope>`) </soap:Envelope>`]
break; const [newMsgValue, setNewMsgValue] = useState(possibleMsgs[age-1])
default: const [loading, setLoading] = useState(false);
// code block
const handleNewMessageValue = (event) => {
setNewMsgValue(event.target.value)
} }
const handleClose = () => {
setOpen(false);
}; };
const handleChange = (event) => { const handleCancelNewMsgTemplate = () => {
setValue(event.target.value); setNewMessage(false)
setNewMsgName("")
setNewMsgValue(possibleMsgs[age-1])
// setValue(possibleMsgs[age-1])
}
const saveMsg = async () => {
let {status} = await httpRequest(
`/api/device/message?name=`+message[currentMsg].name,
"PUT",
value,
null,
)
if ( status === 204){
setSaveChanges(false)
setMessage(message.map((msg, index) => {
if (index === currentMsg) {
return {...msg, value: value}
}else{
return msg
}
}))
}
}
const createNewMsg = async () => {
setLoading(true)
let {status} = await httpRequest(
`/api/device/message/cwmp?name=`+newMsgName,
"POST",
newMsgValue,
null,
)
if ( status === 204){
setNewMessage(false)
setNewMsgName("")
let result = await fetchMessages()
if (result) {
setCurrentMsg(result.length-1)
}
setValue(newMsgValue)
setNewMsgValue(possibleMsgs[age-1])
}
setLoading(false)
}
const handleChangeMessage = (event) => {
setSaveChanges(false)
setCurrentMsg(event.target.value)
setValue(message[event.target.value].value)
}
const handleDeleteMessage = async () => {
let {status} = await httpRequest(
`/api/device/message?name=`+message[currentMsg].name.replace(" ", '+'),
"DELETE",
)
if ( status === 204){
fetchMessages()
setCurrentMsg(0)
setValue("")
}
}
const handleOpen = async () => {
setOpen(true);
let {result, status} = await httpRequest(
`/api/device/cwmp/${router.query.id[0]}/generic`,
"PUT",
value,
null,
"text",
)
if (status === 200){
setAnswer(true)
console.log("result:",result)
let answer = prettifyXml(result)
if (answer == "null"){
answer = result
}
console.log(answer)
setContent(answer)
}
setOpen(false)
}
const fetchMessages = async () => {
let {result, status} = await httpRequest(
`/api/device/message?type=cwmp`,
"GET",
null,
null,
)
if ( status === 200){
setMessage(result)
setValue(result ? result[0].value : "")
return result
}
}
const handleChangeRPC = (event) => {
setAge(event.target.value);
setNewMsgValue(possibleMsgs[event.target.value-1])
}; };
const handleEditMessage = (event) => {
setSaveChanges(true)
setValue(event.target.value)
}
const handleSubmit = useCallback( const handleSubmit = useCallback(
(event) => { (event) => {
event.preventDefault(); event.preventDefault();
@ -206,47 +285,83 @@ const handleOpen = () => {
[] []
); );
useEffect(() => {
fetchMessages();
},[]);
return ( return (
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<Card> <Card>
<CardActions sx={{ justifyContent: 'flex-end'}}> <CardHeader sx={{ justifyContent: 'flex-end'}}
<FormControl sx={{width:'100px'}}> avatar={<SvgIcon>< EnvelopeIcon/></SvgIcon>}
<Select title="Custom Message"
labelId="demo-simple-select-standard-label" action={
id="demo-simple-select-standard" <Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
value={age} <Button sx={{ backgroundColor: "rgba(48, 109, 111, 0.04)" }}
label="Action" endIcon={<SvgIcon><PlusCircleIcon /></SvgIcon>}
onChange={(event)=>{handleChangeRPC(event)}} onClick={()=>{setNewMessage(true)}}
variant='standard'
> >
<MenuItem value={1}>Create</MenuItem> <Stack direction={"row"} spacing={1}>
<MenuItem value={2}>Read</MenuItem> New Message
<MenuItem value={3}>Update</MenuItem> </Stack>
<MenuItem value={4}>Delete</MenuItem> </Button>
</Select> </Stack>}
</FormControl> >
</CardActions> </CardHeader>
<Divider /> <Divider />
<CardContent> <CardContent>
<Stack pb={4} spacing={5} direction={"row"}>
<FormControl sx={{display:"flex", width: "15%"}} variant="standard" >
<InputLabel>Message</InputLabel>
<Select
value={currentMsg}
onChange={(event)=>{handleChangeMessage(event)}}
>
{message && message.map((msg, index) => {
return <MenuItem value={index}>{msg.name}</MenuItem>
})}
</Select>
</FormControl>
</Stack>
<Stack <Stack
spacing={3} spacing={3}
alignItems={'stretch'} alignItems={'stretch'}
> >
<TextField {!loadingSaveMsg ? <TextField
id="outlined-multiline-static" id="outlined-multiline-static"
size="large" size="large"
multiline="true" multiline="true"
label="Mensagem" // label="Payload"
name="password" name="password"
onChange={handleChange} onChange={handleEditMessage}
value={value} value={value}
variant="filled"
fullWidth fullWidth
rows="15" rows="15"
/> />:<CircularProgress />}
</Stack> </Stack>
</CardContent> </CardContent>
<Divider /> {/* <Divider /> */}
<CardActions sx={{ justifyContent: 'flex-end' }}> <CardActions>
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-start"}>
<Button
variant="contained"
endIcon={<SvgIcon><TrashIcon /></SvgIcon>}
onClick={handleDeleteMessage}
disabled={!message}
>
Delete
</Button>
{!loadingSaveMsg ? <Button
variant="contained"
endIcon={<SvgIcon><DocumentArrowDown /></SvgIcon>}
onClick={saveMsg}
disabled={!saveChanges}
>
Save
</Button>: <CircularProgress />}
</Stack>
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
<Button <Button
variant="contained" variant="contained"
endIcon={<SvgIcon><PaperAirplane /></SvgIcon>} endIcon={<SvgIcon><PaperAirplane /></SvgIcon>}
@ -254,6 +369,7 @@ const handleOpen = () => {
> >
Send Send
</Button> </Button>
</Stack>
</CardActions> </CardActions>
<Backdrop <Backdrop
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }} sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
@ -307,6 +423,83 @@ const handleOpen = () => {
}}>Ok</Button> }}>Ok</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
<Dialog open={newMessage} maxWidth={"800px"}>
<DialogTitle>
<SvgIcon><EnvelopeIcon/></SvgIcon>
</DialogTitle>
<DialogContent>
<Stack
direction={"row"}
container
pb={3}
// direction="column"
// alignItems="center"
// justifyContent="center"
pt={1}
spacing={3}
>
<TextField
variant='standard'
fullWidth
value={newMsgName}
onChange={(event)=>{setNewMsgName(event.target.value)}}
label="Name"
sx={{maxWidth: "30%", justifyContent:"center"}}
/>
<FormControl sx={{display:"flex", width: "30%"}} variant="standard" >
<InputLabel>Template</InputLabel>
<Select
value={age}
label="Action"
name='action'
onChange={(event)=>{handleChangeRPC(event)}}
>
<MenuItem value={1}>SetParameterValues</MenuItem>
<MenuItem value={2}>DeleteObject</MenuItem>
<MenuItem value={3}>AddObject</MenuItem>
<MenuItem value={4}>Reboot</MenuItem>
<MenuItem value={5}>GetParameterValues</MenuItem>
<MenuItem value={6}>GetParameterNames</MenuItem>
<MenuItem value={7}>GetParameterAttributes</MenuItem>
</Select>
</FormControl>
</Stack>
<Stack
spacing={3}
alignItems={'stretch'}
width={"600px"}
>
<TextField
id="outlined-multiline-static"
size="large"
multiline="true"
label="Payload"
name="password"
onChange={handleNewMessageValue}
value={newMsgValue}
// fullWidth
// rows="15"
/>
</Stack>
</DialogContent>
{/* <Divider/> */}
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"} p={2}>
<Button
variant="contained"
onClick={handleCancelNewMsgTemplate}
>
Cancel
</Button>
{!loading ?
<Button
variant="contained"
endIcon={<SvgIcon><CheckIcon /></SvgIcon>}
onClick={createNewMsg}
>
Save
</Button>:<CircularProgress />}
</Stack>
</Dialog>
</Card> </Card>
</form> </form>
); );

View File

@ -19,91 +19,90 @@ import {
DialogContentText, DialogContentText,
DialogActions, DialogActions,
Box, Box,
IconButton IconButton,
Grid
} from '@mui/material'; } from '@mui/material';
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon'; import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon'; import PaperAirplane from '@heroicons/react/24/solid/PaperAirplaneIcon';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import Backdrop from '@mui/material/Backdrop'; import Backdrop from '@mui/material/Backdrop';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useBackendContext } from 'src/contexts/backend-context';
import DocumentArrowDown from '@heroicons/react/24/outline/DocumentArrowDownIcon';
import TrashIcon from '@heroicons/react/24/outline/TrashIcon';
import PlusCircleIcon from '@heroicons/react/24/outline/PlusCircleIcon';
import EnvelopeIcon from '@heroicons/react/24/outline/EnvelopeIcon';
import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
export const DevicesRPC = () => { export const DevicesRPC = () => {
const router = useRouter() const router = useRouter()
let { httpRequest } = useBackendContext()
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [scroll, setScroll] = useState('paper'); const [scroll, setScroll] = useState('paper');
const [answer, setAnswer] = useState(false) const [answer, setAnswer] = useState(false)
const [content, setContent] = useState('') const [content, setContent] = useState('')
const [age, setAge] = useState(2); const [age, setAge] = useState(6);
const [newMessage, setNewMessage] = useState(false)
const [value, setValue] = useState(`{ const [message, setMessage] = useState(null)
"param_paths": [ const [currentMsg, setCurrentMsg] = useState(0)
"Device.WiFi.SSID.[Name==wlan0].", const [newMsgName, setNewMsgName] = useState("")
"Device.IP.Interface.*.Alias", const [value, setValue] = useState()
"Device.DeviceInfo.FirmwareImage.*.Alias", const [saveChanges, setSaveChanges] = useState(false)
"Device.IP.Interface.1.IPv4Address.1.IPAddress" const [loadingSaveMsg, setLoadingSaveMsg] = useState(false)
], const possibleMsgs = [
"max_depth": 2 `{
}`) "header": {
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
const handleClose = () => { "msg_type": 4
setOpen(false); },
}; "body": {
const handleOpen = () => { "request": {
setOpen(true); "set": {
var myHeaders = new Headers(); "allow_partial":true,
myHeaders.append("Content-Type", "application/json"); "update_objs":[
myHeaders.append("Authorization", localStorage.getItem("token")); {
"obj_path":"Device.IP.Interface.1.",
var raw = value "param_settings":[
{
var requestOptions = { "param":"Alias",
method: 'PUT', "value":"test",
headers: myHeaders, "required":true
body: raw,
redirect: 'follow'
};
var method;
switch(age) {
case 1:
method="add"
break;
case 2:
method="get"
break;
case 3:
method="set"
break;
case 4:
method="del"
break;
} }
]
fetch(`${process.env.NEXT_PUBLIC_REST_ENDPOINT || ""}/api/device/${router.query.id[0]}/any/${method}`, requestOptions)
.then(response => response.text())
.then(result => {
if (result.status === 401){
router.push("/auth/login")
} }
setOpen(false) ]
setAnswer(true) }
let teste = JSON.stringify(JSON.parse(result), null, 2) }
console.log(teste) }
setContent(teste) }`,
}) `{
.catch(error => console.log('error', error)); "header": {
}; "msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
"msg_type": 10
const handleChangeRPC = (event) => { },
setAge(event.target.value); "body": {
switch(event.target.value) { "request": {
case 1: "delete": {
setValue(`{ "allow_partial": true,
"obj_paths": [
"Device.IP.Interface.[Alias==test]."
]
}
}
}
}`,
`
{
"header": {
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
"msg_type": 8
},
"body": {
"request": {
"add": {
"allow_partial": true, "allow_partial": true,
"create_objs": [ "create_objs": [
{ {
@ -117,54 +116,200 @@ const handleOpen = () => {
] ]
} }
] ]
}`) }
break; }
case 2: }
setValue(`{ }`,
"param_paths": [ `{
"header": {
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
"msg_type": 6
},
"body": {
"request": {
"operate": {
"command": "Device.Reboot()",
"send_resp": true
}
}
}
}`,
`{
"header": {
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
"msg_type": 1
},
"body": {
"request": {
"get": {
"paramPaths": [
"Device.WiFi.SSID.[Name==wlan0].", "Device.WiFi.SSID.[Name==wlan0].",
"Device.IP.Interface.*.Alias", "Device.IP.Interface.*.Alias",
"Device.DeviceInfo.FirmwareImage.*.Alias", "Device.DeviceInfo.FirmwareImage.*.Alias",
"Device.IP.Interface.1.IPv4Address.1.IPAddress" "Device.IP.Interface.1.IPv4Address.1.IPAddress"
], ],
"max_depth": 2 "maxDepth": 2
}`)
break;
case 3:
setValue(`
{
"allow_partial":true,
"update_objs":[
{
"obj_path":"Device.IP.Interface.[Alias==pamonha].",
"param_settings":[
{
"param":"Alias",
"value":"goiaba",
"required":true
} }
]
} }
] }
}`) }`,`{
break; "header": {
case 4: "msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
setValue(`{ "msg_type": 12
"allow_partial": true, },
"body": {
"request": {
"get_supported_dm": {
"obj_paths" : [ "obj_paths" : [
"Device.IP.Interface.3." "Device."
] ],
}`) "first_level_only" : false,
break; "return_commands" : false,
default: "return_events" : false,
// code block "return_params" : true
} }
}
}
}`,
`{
"header": {
"msg_id": "b7dc38ea-aefb-4761-aa55-edaa97adb2f0",
"msg_type": 14
},
"body": {
"request": {
"get_instances": {
"obj_paths" : ["Device.DeviceInfo."],
"first_level_only" : false
}
}
}
}`]
const [newMsgValue, setNewMsgValue] = useState(possibleMsgs[age-1])
const [loading, setLoading] = useState(false);
const handleNewMessageValue = (event) => {
setNewMsgValue(event.target.value)
}
const handleClose = () => {
setOpen(false);
}; };
const handleChange = (event) => { const handleCancelNewMsgTemplate = () => {
setValue(event.target.value); setNewMessage(false)
setNewMsgName("")
setNewMsgValue(possibleMsgs[age-1])
// setValue(possibleMsgs[age-1])
}
const saveMsg = async () => {
let {status} = await httpRequest(
`/api/device/message?name=`+message[currentMsg].name,
"PUT",
value,
null,
)
if ( status === 204){
setSaveChanges(false)
setMessage(message.map((msg, index) => {
if (index === currentMsg) {
return {...msg, value: value}
}else{
return msg
}
}))
}
}
const createNewMsg = async () => {
setLoading(true)
let {status} = await httpRequest(
`/api/device/message/usp?name=`+newMsgName,
"POST",
newMsgValue,
null,
)
if ( status === 204){
setNewMessage(false)
setNewMsgName("")
let result = await fetchMessages()
if (result) {
setCurrentMsg(result.length-1)
}
setValue(newMsgValue)
setNewMsgValue(possibleMsgs[age-1])
}
setLoading(false)
}
const handleChangeMessage = (event) => {
setSaveChanges(false)
setCurrentMsg(event.target.value)
setValue(message[event.target.value].value)
}
const handleDeleteMessage = async () => {
let {status} = await httpRequest(
`/api/device/message?name=`+message[currentMsg].name.replace(" ", '+'),
"DELETE",
)
if ( status === 204){
fetchMessages()
setCurrentMsg(0)
setValue("")
}
}
const handleOpen = async () => {
setOpen(true);
let {result, status} = await httpRequest(
`/api/device/${router.query.id[0]}/any/generic`,
"PUT",
value,
null,
)
if (status === 200){
setAnswer(true)
console.log("result:",result)
let answer = JSON.stringify(result, null, 2)
if (answer == "null"){
answer = result
}
console.log(answer)
setContent(answer)
}
setOpen(false)
}
const fetchMessages = async () => {
let {result, status} = await httpRequest(
`/api/device/message?type=usp`,
"GET",
null,
null,
)
if ( status === 200){
setMessage(result)
setValue(result ? result[0].value : "")
return result
}
}
const handleChangeRPC = (event) => {
setAge(event.target.value);
setNewMsgValue(possibleMsgs[event.target.value-1])
}; };
const handleEditMessage = (event) => {
if (message) {
setSaveChanges(true)
}
setValue(event.target.value)
}
const handleSubmit = useCallback( const handleSubmit = useCallback(
(event) => { (event) => {
event.preventDefault(); event.preventDefault();
@ -172,47 +317,83 @@ const handleOpen = () => {
[] []
); );
useEffect(() => {
fetchMessages();
},[]);
return ( return (
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<Card> <Card>
<CardActions sx={{ justifyContent: 'flex-end'}}> <CardHeader sx={{ justifyContent: 'flex-end'}}
<FormControl sx={{width:'100px'}}> avatar={<SvgIcon>< EnvelopeIcon/></SvgIcon>}
<Select title="Custom Message"
labelId="demo-simple-select-standard-label" action={
id="demo-simple-select-standard" <Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
value={age} <Button sx={{ backgroundColor: "rgba(48, 109, 111, 0.04)" }}
label="Action" endIcon={<SvgIcon><PlusCircleIcon /></SvgIcon>}
onChange={(event)=>{handleChangeRPC(event)}} onClick={()=>{setNewMessage(true)}}
variant='standard'
> >
<MenuItem value={1}>Create</MenuItem> <Stack direction={"row"} spacing={1}>
<MenuItem value={2}>Read</MenuItem> New Message
<MenuItem value={3}>Update</MenuItem> </Stack>
<MenuItem value={4}>Delete</MenuItem> </Button>
</Select> </Stack>}
</FormControl> >
</CardActions> </CardHeader>
<Divider /> <Divider />
<CardContent> <CardContent>
<Stack pb={4} spacing={5} direction={"row"}>
<FormControl sx={{display:"flex", width: "15%"}} variant="standard" >
<InputLabel>Message</InputLabel>
<Select
value={currentMsg}
onChange={(event)=>{handleChangeMessage(event)}}
>
{message && message.map((msg, index) => {
return <MenuItem value={index}>{msg.name}</MenuItem>
})}
</Select>
</FormControl>
</Stack>
<Stack <Stack
spacing={3} spacing={3}
alignItems={'stretch'} alignItems={'stretch'}
> >
<TextField {!loadingSaveMsg ? <TextField
id="outlined-multiline-static" id="outlined-multiline-static"
size="large" size="large"
multiline="true" multiline="true"
label="Mensagem" // label="Payload"
name="password" name="password"
onChange={handleChange} onChange={handleEditMessage}
value={value} value={value}
variant="filled"
fullWidth fullWidth
rows="15" rows="15"
/> />:<CircularProgress />}
</Stack> </Stack>
</CardContent> </CardContent>
<Divider /> {/* <Divider /> */}
<CardActions sx={{ justifyContent: 'flex-end' }}> <CardActions>
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-start"}>
<Button
variant="contained"
endIcon={<SvgIcon><TrashIcon /></SvgIcon>}
onClick={handleDeleteMessage}
disabled={!message}
>
Delete
</Button>
{!loadingSaveMsg ? <Button
variant="contained"
endIcon={<SvgIcon><DocumentArrowDown /></SvgIcon>}
onClick={saveMsg}
disabled={!saveChanges}
>
Save
</Button>: <CircularProgress />}
</Stack>
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"}>
<Button <Button
variant="contained" variant="contained"
endIcon={<SvgIcon><PaperAirplane /></SvgIcon>} endIcon={<SvgIcon><PaperAirplane /></SvgIcon>}
@ -220,6 +401,7 @@ const handleOpen = () => {
> >
Send Send
</Button> </Button>
</Stack>
</CardActions> </CardActions>
<Backdrop <Backdrop
sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }} sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
@ -273,6 +455,83 @@ const handleOpen = () => {
}}>Ok</Button> }}>Ok</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
<Dialog open={newMessage} maxWidth={"800px"}>
<DialogTitle>
<SvgIcon><EnvelopeIcon/></SvgIcon>
</DialogTitle>
<DialogContent>
<Stack
direction={"row"}
container
pb={3}
// direction="column"
// alignItems="center"
// justifyContent="center"
pt={1}
spacing={3}
>
<TextField
variant='standard'
fullWidth
value={newMsgName}
onChange={(event)=>{setNewMsgName(event.target.value)}}
label="Name"
sx={{maxWidth: "30%", justifyContent:"center"}}
/>
<FormControl sx={{display:"flex", width: "30%"}} variant="standard" >
<InputLabel>Template</InputLabel>
<Select
value={age}
label="Action"
name='action'
onChange={(event)=>{handleChangeRPC(event)}}
>
<MenuItem value={1}>Set</MenuItem>
<MenuItem value={2}>Delete</MenuItem>
<MenuItem value={3}>Add</MenuItem>
<MenuItem value={4}>Operate</MenuItem>
<MenuItem value={5}>Get</MenuItem>
<MenuItem value={6}>Get Supported DM</MenuItem>
<MenuItem value={7}>Get Instances</MenuItem>
</Select>
</FormControl>
</Stack>
<Stack
spacing={3}
alignItems={'stretch'}
width={"600px"}
>
<TextField
id="outlined-multiline-static"
size="large"
multiline="true"
label="Payload"
name="password"
onChange={handleNewMessageValue}
value={newMsgValue}
// fullWidth
// rows="15"
/>
</Stack>
</DialogContent>
{/* <Divider/> */}
<Stack direction={"row"} spacing={1} width={"100%"} justifyContent={"flex-end"} p={2}>
<Button
variant="contained"
onClick={handleCancelNewMsgTemplate}
>
Cancel
</Button>
{!loading ?
<Button
variant="contained"
endIcon={<SvgIcon><CheckIcon /></SvgIcon>}
onClick={createNewMsg}
>
Save
</Button>:<CircularProgress />}
</Stack>
</Dialog>
</Card> </Card>
</form> </form>
); );