Merge pull request #1350 from hen-ter/homeassistant-widget

Added homeassistant widget
pull/1362/head
shamoon 2 years ago committed by GitHub
commit 4367319478
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -571,5 +571,10 @@
"books": "Books", "books": "Books",
"podcastsDuration": "Duration", "podcastsDuration": "Duration",
"booksDuration": "Duration" "booksDuration": "Duration"
},
"homeassistant": {
"people_home": "People Home",
"lights_on": "Lights On",
"switches_on": "Switches On"
} }
} }

@ -14,7 +14,7 @@ export default function Container({ error = false, children, service }) {
// fields: [ "resources.cpu", "resources.mem", "field"] // fields: [ "resources.cpu", "resources.mem", "field"]
// or even // or even
// fields: [ "resources.cpu", "widget_type.field" ] // fields: [ "resources.cpu", "widget_type.field" ]
visibleChildren = children.filter(child => fields.some(field => { visibleChildren = children?.filter(child => fields.some(field => {
let fullField = field; let fullField = field;
if (!field.includes(".")) { if (!field.includes(".")) {
fullField = `${type}.${field}`; fullField = `${type}.${field}`;

@ -22,6 +22,7 @@ const components = {
gotify: dynamic(() => import("./gotify/component")), gotify: dynamic(() => import("./gotify/component")),
grafana: dynamic(() => import("./grafana/component")), grafana: dynamic(() => import("./grafana/component")),
hdhomerun: dynamic(() => import("./hdhomerun/component")), hdhomerun: dynamic(() => import("./hdhomerun/component")),
homeassistant: dynamic(() => import("./homeassistant/component")),
homebridge: dynamic(() => import("./homebridge/component")), homebridge: dynamic(() => import("./homebridge/component")),
healthchecks: dynamic(() => import("./healthchecks/component")), healthchecks: dynamic(() => import("./healthchecks/component")),
immich: dynamic(() => import("./immich/component")), immich: dynamic(() => import("./immich/component")),

@ -0,0 +1,16 @@
import Container from "components/services/widget/container";
import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
const { widget } = service;
const { data, error } = useWidgetAPI(widget, null, { refreshInterval: 60000 });
if (error) {
return <Container error={error} />;
}
return <Container service={service}>
{data?.map(d => <Block label={d.label} value={d.value} key={d.label} />)}
</Container>;
}

@ -0,0 +1,89 @@
import { httpProxy } from "utils/proxy/http";
import getServiceWidget from "utils/config/service-helpers";
import createLogger from "utils/logger";
const logger = createLogger("homeassistantProxyHandler");
const defaultQueries = [
{
template: "{{ states.person|selectattr('state','equalto','home')|list|length }} / {{ states.person|list|length }}",
label: "homeassistant.people_home"
},
{
template: "{{ states.light|selectattr('state','equalto','on')|list|length }} / {{ states.light|list|length }}",
label: "homeassistant.lights_on"
},
{
template: "{{ states.switch|selectattr('state','equalto','on')|list|length }} / {{ states.switch|list|length }}",
label: "homeassistant.switches_on"
}
];
function formatOutput(output, data) {
return output.replace(/\{.*?\}/g,
(match) => match.replace(/\{|\}/g, "").split(".").reduce((o, p) => o ? o[p] : "", data) ?? "");
}
async function getQuery(query, { url, key }) {
const headers = { Authorization: `Bearer ${key}` };
const { state, template, label, value } = query;
if (state) {
return {
result: await httpProxy(new URL(`${url}/api/states/${state}`), {
headers,
method: "GET"
}),
output: (data) => {
const jsonData = JSON.parse(data);
return {
label: formatOutput(label ?? "{attributes.friendly_name}", jsonData),
value: formatOutput(value ?? "{state} {attributes.unit_of_measurement}", jsonData)
};
}
};
}
if (template) {
return {
result: await httpProxy(new URL(`${url}/api/template`), {
headers,
method: "POST",
body: JSON.stringify({ template })
}),
output: (data) => ({ label, value: data.toString() })
};
}
return { result: [500, null, { error: { message: `invalid query ${JSON.stringify(query)}` } }] };
}
export default async function homeassistantProxyHandler(req, res) {
const { group, service } = req.query;
if (!group || !service) {
logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
return res.status(400).json({ error: "Invalid proxy service type" });
}
const widget = await getServiceWidget(group, service);
if (!widget) {
logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
return res.status(400).json({ error: "Invalid proxy service type" });
}
let queries = defaultQueries;
if (!widget.fields && widget.custom) {
queries = widget.custom.slice(0, 4);
}
const results = await Promise.all(queries.map(q => getQuery(q, widget)));
const err = results.find(r => r.result[2]?.error);
if (err) {
const [status, , data] = err.result;
return res.status(status).send(data);
}
return res.status(200).send(results.map(r => {
const [status, , data] = r.result;
return status === 200 ? r.output(data) : { label: status, value: data.toString() };
}));
}

@ -0,0 +1,7 @@
import homeassistantProxyHandler from "./proxy";
const widget = {
proxyHandler: homeassistantProxyHandler,
};
export default widget;

@ -17,6 +17,7 @@ import gluetun from "./gluetun/widget";
import gotify from "./gotify/widget"; import gotify from "./gotify/widget";
import grafana from "./grafana/widget"; import grafana from "./grafana/widget";
import hdhomerun from "./hdhomerun/widget"; import hdhomerun from "./hdhomerun/widget";
import homeassistant from "./homeassistant/widget";
import homebridge from "./homebridge/widget"; import homebridge from "./homebridge/widget";
import healthchecks from "./healthchecks/widget"; import healthchecks from "./healthchecks/widget";
import immich from "./immich/widget"; import immich from "./immich/widget";
@ -94,6 +95,7 @@ const widgets = {
gotify, gotify,
grafana, grafana,
hdhomerun, hdhomerun,
homeassistant,
homebridge, homebridge,
healthchecks, healthchecks,
immich, immich,

Loading…
Cancel
Save