diff --git a/docs/widgets/services/esphome.md b/docs/widgets/services/esphome.md new file mode 100644 index 000000000..6038cb61f --- /dev/null +++ b/docs/widgets/services/esphome.md @@ -0,0 +1,16 @@ +--- +title: ESPHome +description: ESPHome Widget Configuration +--- + +Learn more about [ESPHome](https://esphome.io/). + +Show the number of ESPHome devices based on their state. + +Allowed fields: `["total", "online", "offline", "unknown"]`. + +```yaml +widget: + type: esphome + url: http://esphome.host.or.ip:port +``` diff --git a/mkdocs.yml b/mkdocs.yml index 4c574e18e..b7f8ec6ae 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -49,6 +49,7 @@ nav: - widgets/services/diskstation.md - widgets/services/downloadstation.md - widgets/services/emby.md + - widgets/services/esphome.md - widgets/services/evcc.md - widgets/services/fileflows.md - widgets/services/flood.md diff --git a/public/locales/en/common.json b/public/locales/en/common.json index f6c1b8415..b040e1fd3 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -107,6 +107,12 @@ "episodes": "Episodes", "songs": "Songs" }, + "esphome": { + "offline": "Offline", + "online": "Online", + "total": "Total", + "unknown": "Unknown" + }, "evcc": { "pv_power": "Production", "battery_soc": "Battery", diff --git a/src/widgets/components.js b/src/widgets/components.js index 74d5fe1fd..8b9c277d1 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -23,6 +23,7 @@ const components = { docker: dynamic(() => import("./docker/component")), kubernetes: dynamic(() => import("./kubernetes/component")), emby: dynamic(() => import("./emby/component")), + esphome: dynamic(() => import("./esphome/component")), evcc: dynamic(() => import("./evcc/component")), fileflows: dynamic(() => import("./fileflows/component")), flood: dynamic(() => import("./flood/component")), diff --git a/src/widgets/esphome/component.jsx b/src/widgets/esphome/component.jsx new file mode 100644 index 000000000..c44352fa4 --- /dev/null +++ b/src/widgets/esphome/component.jsx @@ -0,0 +1,41 @@ +import { useTranslation } from "next-i18next"; + +import Block from "components/services/widget/block"; +import Container from "components/services/widget/container"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +export default function Component({ service }) { + const { t } = useTranslation(); + + const { widget } = service; + const { data: resultData, error: resultError } = useWidgetAPI(widget); + + if (resultError) { + return ; + } + + if (!resultData) { + return ( + + + + + + + ); + } + + const total = Object.keys(resultData).length; + const online = Object.entries(resultData).filter(([, v]) => v === true).length; + const offline = Object.entries(resultData).filter(([, v]) => v === false).length; + const unknown = Object.entries(resultData).filter(([, v]) => v === null).length; + + return ( + + + + + + + ); +} diff --git a/src/widgets/esphome/widget.js b/src/widgets/esphome/widget.js new file mode 100644 index 000000000..c5a87b682 --- /dev/null +++ b/src/widgets/esphome/widget.js @@ -0,0 +1,8 @@ +import genericProxyHandler from "utils/proxy/handlers/generic"; + +const widget = { + api: "{url}/ping", + proxyHandler: genericProxyHandler, +}; + +export default widget; diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 2eae4ba90..11cc8af93 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -17,6 +17,7 @@ import deluge from "./deluge/widget"; import diskstation from "./diskstation/widget"; import downloadstation from "./downloadstation/widget"; import emby from "./emby/widget"; +import esphome from "./esphome/widget"; import evcc from "./evcc/widget"; import fileflows from "./fileflows/widget"; import flood from "./flood/widget"; @@ -127,6 +128,7 @@ const widgets = { diskstation, downloadstation, emby, + esphome, evcc, fileflows, flood,