UNPKG

@hakit/core

Version:

A collection of React hooks and helpers for Home Assistant to easily communicate with the Home Assistant WebSocket API.

177 lines (176 loc) 6.51 kB
import "lodash"; import { X as d, Y as A, i as v } from "../../../index-BDZyTvOW.js"; import { computeDomain as y } from "../../utils/computeDomain.js"; import "home-assistant-js-websocket"; import "../../utils/date.js"; import "react"; import "@iconify/react"; import "use-debounce"; import "../useLocale/locales/index.js"; const O = ["climate", "humidifier", "water_heater"], C = ["climate", "humidifier", "input_datetime", "water_heater", "person", "device_tracker"], E = [ "temperature", "current_temperature", "target_temp_low", "target_temp_high", "hvac_action", "humidity", "mode", "action", "current_humidity" ], k = (e) => C.includes(y(e)), Q = ({ connection: e, entityIds: s, callbackFunction: n, hoursToShow: i = 24, minimalResponse: t = !0, significantChangesOnly: o = !0, noAttributes: u }) => { const r = { type: "history/stream", entity_ids: s, start_time: new Date((/* @__PURE__ */ new Date()).getTime() - 3600 * i * 1e3).toISOString(), minimal_response: t, significant_changes_only: o, no_attributes: u ?? !s.some((c) => k(c)) }, m = new j(i); return e.subscribeMessage((c) => n(m.processMessage(c)), r); }; class j { hoursToShow; combinedHistory; constructor(s) { this.hoursToShow = s, this.combinedHistory = {}; } processMessage(s) { if (!this.combinedHistory || !Object.keys(this.combinedHistory).length) return this.combinedHistory = s.states, this.combinedHistory; if (!Object.keys(s.states).length) return this.combinedHistory; const n = this.hoursToShow ? ((/* @__PURE__ */ new Date()).getTime() - 3600 * this.hoursToShow * 1e3) / 1e3 : void 0, i = {}; for (const t of Object.keys(this.combinedHistory)) i[t] = []; for (const t of Object.keys(s.states)) i[t] = []; for (const t of Object.keys(i)) { if (t in this.combinedHistory && t in s.states) { const o = this.combinedHistory[t], u = o[o.length - 1]; i[t] = o.concat(s.states[t]), s.states[t][0].lu < u.lu && (i[t] = i[t].sort((r, m) => r.lu - m.lu)); } else t in this.combinedHistory ? i[t] = this.combinedHistory[t] : i[t] = s.states[t]; if (n && t in this.combinedHistory) { const o = i[t].filter((r) => r.lu < n); if (!o.length || (i[t] = i[t].filter((r) => r.lu >= n), i[t].length && i[t][0].lu === n)) continue; const u = o[o.length - 1]; u.lu = n, delete u.lc, i[t].unshift(u); } } return this.combinedHistory = i, this.combinedHistory; } } const H = (e, s) => e.state === s.state && // Only compare attributes if both states have an attributes object. // When `minimal_response` is sent, only the first and last state // will have attributes except for domains in DOMAINS_USE_LAST_UPDATED. (!e.attributes || !s.attributes || E.every((n) => e.attributes[n] === s.attributes[n])), U = (e, s, n) => { const i = d.getState().entities, t = []; return Object.keys(n).forEach((o) => { const u = n[o], r = u[0], m = y(o), c = []; for (const a of u) { let l; if (O.includes(m)) { l = { state: a.s, last_changed: a.lu * 1e3, attributes: {} }; for (const h of E) h in a.a && (l.attributes[h] = a.a[h]); } else l = { state: a.s, // lc (last_changed) may be omitted if its the same // as lu (last_updated). last_changed: (a.lc ? a.lc : a.lu) * 1e3, attributes: {} }; c.length > 1 && H(l, c[c.length - 1]) && H(l, c[c.length - 2]) || c.push(l); } const g = o in i ? i[o].attributes : "friendly_name" in r.a ? r.a : void 0; t.push({ domain: m, name: v(o, g || {}), entity_id: o, states: c }); }), { unit: e, device_class: s, identifier: Object.keys(n).join(""), data: t }; }, L = (e, s, n) => { const i = [], t = s[0], o = d.getState().formatter, u = d.getState().entities; for (const r of s) { if (i.length > 0 && r.s === i[i.length - 1].state) continue; const m = {}; n?.attributes.device_class && (m.device_class = n?.attributes.device_class); const c = u[e]; i.push({ state_localize: o.attributeValue( { ...c, attributes: { ...r.a || t.a, ...m } }, r.s ), state: r.s, // lc (last_changed) may be omitted if its the same // as lu (last_updated). last_changed: (r.lc ? r.lc : r.lu) * 1e3 }); } return { name: v(e, n?.attributes || t.a), entity_id: e, data: i }; }, B = ["counter", "input_number", "number"], D = (e) => B.includes(e), T = (e) => "unit_of_measurement" in e || "state_class" in e, F = (e, s) => e.attributes.device_class != null && s.includes(e.attributes.device_class), K = (e, s, n, i, t = !1) => t || D(e) || s != null && T(s.attributes) || s != null && e === "sensor" && F(s, i) || n != null, x = " ", z = (e, s, n) => n ? `${e}_${s || ""}` : e, W = (e, s, n = !1, i = !1) => { const t = {}, o = [], u = {}, r = d.getState().sensorNumericDeviceClasses, m = d.getState().config, c = d.getState().entities; return e.entity_id in s ? u[e.entity_id] = s[e.entity_id] : c[e.entity_id] && (u[e.entity_id] = [ { s: c[e.entity_id].state, a: c[e.entity_id].attributes, lu: new Date(c[e.entity_id].last_updated).getTime() / 1e3 } ]), u ? (Object.keys(s).forEach((a) => { const l = u[a]; if (l.length === 0) return; const h = y(a), _ = a in c ? c[a] : void 0, p = _ || D(h) ? void 0 : l.find((S) => S.a && T(S.a)), N = K(h, _, p, r, n); let b; N ? b = _?.attributes.unit_of_measurement || p?.a.unit_of_measurement || x : b = { zone: A("unit"), climate: m?.unit_system.temperature, humidifier: "%", water_heater: m?.unit_system.temperature }[h]; const w = { climate: "temperature", humidifier: "humidity", water_heater: "temperature" }[h] || (_?.attributes || p?.a)?.device_class, f = z(b, w, i); b ? f && f in t && a in t[f] ? t[f][a].push(...l) : f && (f in t || (t[f] = {}), t[f][a] = l) : o.push(L(a, l, _)); }), { line: Object.keys(t).map((a) => { const l = a.split("_"), h = l[0], _ = l.slice(1).join("_") || void 0; return U(h, _, t[a]); }), timeline: o }) : { line: [], timeline: [] }; }; export { W as computeHistory, Q as subscribeHistory }; //# sourceMappingURL=history.js.map