@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
JavaScript
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