add peanut info widget

This commit is contained in:
Brandon McFarlin 2024-12-13 00:21:14 -05:00
parent d3cabec07b
commit 8c64b3f28a
3 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,60 @@
import useSWR from "swr";
import { FaCarBattery } from "react-icons/fa";
import { useTranslation } from "next-i18next";
import Error from "../widget/error";
import Resource from "../widget/resource";
export default function Widget({ options }) {
const { t } = useTranslation();
const { expanded } = options;
let { refresh } = options;
if (!refresh) refresh = 1500;
const { data, error } = useSWR(
`/api/widgets/peanut?${new URLSearchParams({ ...options }).toString()}`,
{
refreshInterval: refresh,
},
);
if (error || data?.error) {
return <Error options={options} />;
}
if (!data) {
return (
<Resource
icon={FaCarBattery}
value="-"
label="Load"
expandedValue="-"
expandedLabel="Battery"
expanded={expanded}
percentage="0"
/>
);
}
return (
<Resource
icon={FaCarBattery}
value={t("common.number", {
value: data['ups.load'],
style: "unit",
unit: "percent",
maximumFractionDigits: 0,
})}
label="Load"
expandedValue={t("common.number", {
value: data['battery.charge'],
style: "unit",
unit: "percent",
maximumFractionDigits: 0,
})}
expandedLabel="Battery"
percentage={data['ups.load']}
expanded={expanded}
/>
);
}

View File

@ -12,6 +12,7 @@ const widgetMappings = {
logo: dynamic(() => import("components/widgets/logo/logo"), { ssr: false }),
unifi_console: dynamic(() => import("components/widgets/unifi_console/unifi_console")),
glances: dynamic(() => import("components/widgets/glances/glances")),
peanut: dynamic(() => import("components/widgets/peanut/peanut")),
openmeteo: dynamic(() => import("components/widgets/openmeteo/openmeteo")),
longhorn: dynamic(() => import("components/widgets/longhorn/longhorn")),
kubernetes: dynamic(() => import("components/widgets/kubernetes/kubernetes")),

View File

@ -0,0 +1,55 @@
import { httpProxy } from "utils/proxy/http";
import createLogger from "utils/logger";
import { getPrivateWidgetOptions } from "utils/config/widget-helpers";
const logger = createLogger("peanut");
async function retrieveFromPeanutAPI(privateWidgetOptions, ups) {
let errorMessage;
const url = privateWidgetOptions?.options?.url;
if (!url) {
errorMessage = "Missing PeaNUT URL";
logger.error(errorMessage);
throw new Error(errorMessage);
}
const apiUrl = `${url}/api/v1/devices/${ups || privateWidgetOptions?.options?.key}`;
const headers = {
"Accept-Encoding": "application/json",
};
const params = { method: "GET", headers };
const [status, , data] = await httpProxy(apiUrl, params);
if (status === 401) {
errorMessage = `Authorization failure getting data from peanut API. Data: ${data.toString()}`;
logger.error(errorMessage);
throw new Error(errorMessage);
}
if (status !== 200) {
errorMessage = `HTTP ${status} getting data from peanut API. Data: ${data.toString()}`;
logger.error(errorMessage);
throw new Error(errorMessage);
}
return JSON.parse(Buffer.from(data).toString());
}
export default async function handler(req, res) {
const { key } = req.query;
const privateWidgets = await getPrivateWidgetOptions();
const privateWidgetOptions = privateWidgets.find((o) => o.type === "peanut");
try {
const upsData = await retrieveFromPeanutAPI(privateWidgetOptions, key);
const data = {
...upsData
};
return res.status(200).send(data);
} catch (e) {
return res.status(400).json({ error: e.message });
}
}