mirror of
https://github.com/karl0ss/homepage.git
synced 2025-05-02 21:43:39 +01:00
Merge pull request #704 from benphelps/omada-widget
Feature: Omada widget
This commit is contained in:
commit
b9415b43b0
@ -88,6 +88,13 @@
|
|||||||
"bitrate": "Bitrate",
|
"bitrate": "Bitrate",
|
||||||
"no_active": "No Active Streams"
|
"no_active": "No Active Streams"
|
||||||
},
|
},
|
||||||
|
"omada": {
|
||||||
|
"connectedAp": "Connected APs",
|
||||||
|
"activeUser": "Active devices",
|
||||||
|
"alerts": "Alerts",
|
||||||
|
"connectedGateway": "Connected gateways",
|
||||||
|
"connectedSwitches": "Connected switches"
|
||||||
|
},
|
||||||
"nzbget": {
|
"nzbget": {
|
||||||
"rate": "Rate",
|
"rate": "Rate",
|
||||||
"remaining": "Remaining",
|
"remaining": "Remaining",
|
||||||
|
@ -26,6 +26,7 @@ const components = {
|
|||||||
nextdns: dynamic(() => import("./nextdns/component")),
|
nextdns: dynamic(() => import("./nextdns/component")),
|
||||||
npm: dynamic(() => import("./npm/component")),
|
npm: dynamic(() => import("./npm/component")),
|
||||||
nzbget: dynamic(() => import("./nzbget/component")),
|
nzbget: dynamic(() => import("./nzbget/component")),
|
||||||
|
omada: dynamic(() => import("./omada/component")),
|
||||||
ombi: dynamic(() => import("./ombi/component")),
|
ombi: dynamic(() => import("./ombi/component")),
|
||||||
overseerr: dynamic(() => import("./overseerr/component")),
|
overseerr: dynamic(() => import("./overseerr/component")),
|
||||||
paperlessngx: dynamic(() => import("./paperlessngx/component")),
|
paperlessngx: dynamic(() => import("./paperlessngx/component")),
|
||||||
|
39
src/widgets/omada/component.jsx
Normal file
39
src/widgets/omada/component.jsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { useTranslation } from "next-i18next";
|
||||||
|
|
||||||
|
import useWidgetAPI from "../../utils/proxy/use-widget-api";
|
||||||
|
import Container from "../../components/services/widget/container";
|
||||||
|
import Block from "../../components/services/widget/block";
|
||||||
|
|
||||||
|
export default function Component({ service }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { widget } = service;
|
||||||
|
|
||||||
|
const { data: omadaData, error: omadaAPIError } = useWidgetAPI(widget, {
|
||||||
|
refreshInterval: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (omadaAPIError) {
|
||||||
|
return <Container error={omadaAPIError} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!omadaData) {
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="omada.connectedAp" />
|
||||||
|
<Block label="omada.activeUser" />
|
||||||
|
<Block label="omada.alerts" />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container service={service}>
|
||||||
|
<Block label="omada.connectedAp" value={t( "common.number", { value: omadaData.connectedAp})} />
|
||||||
|
<Block label="omada.activeUser" value={t( "common.number", { value: omadaData.activeUser })} />
|
||||||
|
<Block label="omada.alerts" value={t( "common.number", { value: omadaData.alerts })} />
|
||||||
|
{ omadaData.connectedGateways > 0 && <Block label="omada.connectedGateway" value={t("common.number", { value: omadaData.connectedGateways})} /> }
|
||||||
|
{ omadaData.connectedSwitches > 0 && <Block label="omada.connectedSwitches" value={t("common.number", { value: omadaData.connectedSwitches})} /> }
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
252
src/widgets/omada/proxy.js
Normal file
252
src/widgets/omada/proxy.js
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
|
||||||
|
import { httpProxy } from "utils/proxy/http";
|
||||||
|
import getServiceWidget from "utils/config/service-helpers";
|
||||||
|
import createLogger from "utils/logger";
|
||||||
|
|
||||||
|
const proxyName = "omadaProxyHandler";
|
||||||
|
|
||||||
|
const logger = createLogger(proxyName);
|
||||||
|
|
||||||
|
async function login(loginUrl, username, password, controllerVersionMajor) {
|
||||||
|
const params = {
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controllerVersionMajor === 3) {
|
||||||
|
params.method = "login";
|
||||||
|
params.params = {
|
||||||
|
name: username,
|
||||||
|
password
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [status, contentType, data] = await httpProxy(loginUrl, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return [status, JSON.parse(data.toString())];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default async function omadaProxyHandler(req, res) {
|
||||||
|
const { group, service } = req.query;
|
||||||
|
|
||||||
|
if (group && service) {
|
||||||
|
const widget = await getServiceWidget(group, service);
|
||||||
|
|
||||||
|
if (widget) {
|
||||||
|
|
||||||
|
const {url} = widget;
|
||||||
|
|
||||||
|
const controllerInfoURL = `${widget.url}/api/info`;
|
||||||
|
|
||||||
|
let [status, contentType, data] = await httpProxy(controllerInfoURL, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status !== 200) {
|
||||||
|
logger.error("Unable to retrieve Omada controller info");
|
||||||
|
return res.status(status).json({error: {message: `HTTP Error ${status}`, url: controllerInfoURL, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
let cId;
|
||||||
|
let controllerVersion;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cId = JSON.parse(data).result.omadacId;
|
||||||
|
controllerVersion = JSON.parse(data).result.controllerVer;
|
||||||
|
} catch (e) {
|
||||||
|
controllerVersion = "3.2.x"
|
||||||
|
}
|
||||||
|
|
||||||
|
const controllerVersionMajor = parseInt(controllerVersion.split('.')[0], 10)
|
||||||
|
|
||||||
|
if (![3,4,5].includes(controllerVersionMajor)) {
|
||||||
|
return res.status(500).json({error: {message: "Error determining controller version", data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
let loginUrl;
|
||||||
|
|
||||||
|
switch (controllerVersionMajor) {
|
||||||
|
case 3:
|
||||||
|
loginUrl = `${widget.url}/api/user/login?ajax`;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
loginUrl = `${widget.url}/api/v2/login`;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
loginUrl = `${widget.url}/${cId}/api/v2/login`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [loginStatus, loginResponseData] = await login(loginUrl, widget.username, widget.password, controllerVersionMajor);
|
||||||
|
|
||||||
|
if (loginStatus !== 200 || loginResponseData.errorCode > 0) {
|
||||||
|
return res.status(status).json({error: {message: "Error logging in to Oamda controller", url: loginUrl, data: loginResponseData}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { token } = loginResponseData.result;
|
||||||
|
|
||||||
|
let sitesUrl;
|
||||||
|
let body = {};
|
||||||
|
let params = { token };
|
||||||
|
let headers = { "Csrf-Token": token };
|
||||||
|
let method = "GET";
|
||||||
|
|
||||||
|
switch (controllerVersionMajor) {
|
||||||
|
case 3:
|
||||||
|
sitesUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`;
|
||||||
|
body = {
|
||||||
|
"method": "getUserSites",
|
||||||
|
"params": {
|
||||||
|
"userName": widget.username
|
||||||
|
}
|
||||||
|
};
|
||||||
|
method = "POST";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
sitesUrl = `${widget.url}/api/v2/sites?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
sitesUrl = `${widget.url}/${cId}/api/v2/sites?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(sitesUrl, {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const sitesResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
if (sitesResponseData.errorCode > 0) {
|
||||||
|
logger.debug(`HTTTP ${status} getting sites list: ${sitesResponseData.msg}`);
|
||||||
|
return res.status(status).json({error: {message: "Error getting sites list", url, data: sitesResponseData}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const site = (controllerVersionMajor === 3) ?
|
||||||
|
sitesResponseData.result.siteList.find(s => s.name === widget.site):
|
||||||
|
sitesResponseData.result.data.find(s => s.name === widget.site);
|
||||||
|
|
||||||
|
if (!site) {
|
||||||
|
return res.status(status).json({error: {message: `Site ${widget.site} is not found`, url, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
let siteResponseData;
|
||||||
|
|
||||||
|
let connectedAp;
|
||||||
|
let activeUser;
|
||||||
|
let connectedSwitches;
|
||||||
|
let connectedGateways;
|
||||||
|
let alerts;
|
||||||
|
|
||||||
|
if (controllerVersionMajor === 3) {
|
||||||
|
// Omada v3 controller requires switching site
|
||||||
|
const switchUrl = `${widget.url}/web/v1/controller?ajax=&token=${token}`;
|
||||||
|
method = "POST";
|
||||||
|
body = {
|
||||||
|
method: "switchSite",
|
||||||
|
params: {
|
||||||
|
siteName: site.siteName,
|
||||||
|
userName: widget.username
|
||||||
|
}
|
||||||
|
};
|
||||||
|
headers = { "Content-Type": "application/json" };
|
||||||
|
params = { token };
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(switchUrl, {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const switchResponseData = JSON.parse(data);
|
||||||
|
if (status !== 200 || switchResponseData.errorCode > 0) {
|
||||||
|
logger.error(`HTTP ${status} getting sites list: ${data}`);
|
||||||
|
return res.status(status).json({error: {message: "Error switching site", url: switchUrl, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
const statsUrl = `${widget.url}/web/v1/controller?getGlobalStat=&token=${token}`;
|
||||||
|
[status, contentType, data] = await httpProxy(statsUrl, {
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
body: JSON.stringify({
|
||||||
|
"method": "getGlobalStat",
|
||||||
|
}),
|
||||||
|
headers
|
||||||
|
});
|
||||||
|
|
||||||
|
siteResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
if (status !== 200 || siteResponseData.errorCode > 0) {
|
||||||
|
return res.status(status).json({error: {message: "Error getting stats", url: statsUrl, data}});
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedAp = siteResponseData.result.connectedAp;
|
||||||
|
activeUser = siteResponseData.result.activeUser;
|
||||||
|
alerts = siteResponseData.result.alerts;
|
||||||
|
} else if (controllerVersionMajor === 4 || controllerVersionMajor === 5) {
|
||||||
|
const siteName = (controllerVersionMajor === 5) ? site.id : site.key;
|
||||||
|
const siteStatsUrl = (controllerVersionMajor === 4) ?
|
||||||
|
`${url}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}¤tPage=1¤tPageSize=1000` :
|
||||||
|
`${url}/${cId}/api/v2/sites/${siteName}/dashboard/overviewDiagram?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
|
||||||
|
[status, contentType, data] = await httpProxy(siteStatsUrl, {
|
||||||
|
headers: {
|
||||||
|
"Csrf-Token": token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
siteResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
if (status !== 200 || siteResponseData.errorCode > 0) {
|
||||||
|
logger.debug(`HTTP ${status} getting stats for site ${widget.site} with message ${siteResponseData.msg}`);
|
||||||
|
return res.status(500).send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const alertUrl = (controllerVersionMajor === 4) ?
|
||||||
|
`${url}/api/v2/sites/${siteName}/alerts/num?token=${token}¤tPage=1¤tPageSize=1000` :
|
||||||
|
`${url}/${cId}/api/v2/sites/${siteName}/alerts/num?token=${token}¤tPage=1¤tPageSize=1000`;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
[status, contentType, data] = await httpProxy(alertUrl, {
|
||||||
|
headers: {
|
||||||
|
"Csrf-Token": token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const alertResponseData = JSON.parse(data);
|
||||||
|
|
||||||
|
activeUser = siteResponseData.result.totalClientNum;
|
||||||
|
connectedAp = siteResponseData.result.connectedApNum;
|
||||||
|
connectedGateways = siteResponseData.result.connectedGatewayNum;
|
||||||
|
connectedSwitches = siteResponseData.result.connectedSwitchNum;
|
||||||
|
alerts = alertResponseData.result.alertNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.send(JSON.stringify({
|
||||||
|
connectedAp,
|
||||||
|
activeUser,
|
||||||
|
alerts,
|
||||||
|
connectedGateways,
|
||||||
|
connectedSwitches,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(400).json({ error: "Invalid proxy service type" });
|
||||||
|
}
|
7
src/widgets/omada/widget.js
Normal file
7
src/widgets/omada/widget.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import omadaProxyHandler from "./proxy";
|
||||||
|
|
||||||
|
const widget = {
|
||||||
|
proxyHandler: omadaProxyHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default widget;
|
@ -21,6 +21,7 @@ import navidrome from "./navidrome/widget";
|
|||||||
import nextdns from "./nextdns/widget";
|
import nextdns from "./nextdns/widget";
|
||||||
import npm from "./npm/widget";
|
import npm from "./npm/widget";
|
||||||
import nzbget from "./nzbget/widget";
|
import nzbget from "./nzbget/widget";
|
||||||
|
import omada from "./omada/widget";
|
||||||
import ombi from "./ombi/widget";
|
import ombi from "./ombi/widget";
|
||||||
import overseerr from "./overseerr/widget";
|
import overseerr from "./overseerr/widget";
|
||||||
import paperlessngx from "./paperlessngx/widget";
|
import paperlessngx from "./paperlessngx/widget";
|
||||||
@ -73,6 +74,7 @@ const widgets = {
|
|||||||
nextdns,
|
nextdns,
|
||||||
npm,
|
npm,
|
||||||
nzbget,
|
nzbget,
|
||||||
|
omada,
|
||||||
ombi,
|
ombi,
|
||||||
overseerr,
|
overseerr,
|
||||||
paperlessngx,
|
paperlessngx,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user