@glasshome/sync-layer 0.9.1 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/demo/ids.d.ts +5 -0
- package/dist/demo/ids.js +361 -0
- package/dist/index.d.ts +32 -52
- package/dist/index.js +102 -73
- package/dist/solid/index.js +1 -1
- package/dist/track-DssLNusE.js +4959 -0
- package/package.json +7 -1
- package/dist/track-IkwP6XmO.js +0 -2448
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { $ as setPrivilegedConn, A as unloadDemoData, B as getAreaView, C as demoTimeMap, D as resetDemo, E as loadDemoHouse, F as MAX_HISTORY_POINTS, G as getEntityView, H as buildEntityView, I as appendHistoryPoint, J as forceResubscribe, K as getEntityViews, L as bulkAppendHistoryPoints, M as demoEnergyPreferences, N as isEnergyEntity, O as startDemoEnergyTicker, P as synthesizeEnergyHistory, Q as privilegedConn, R as buildAreaView, S as demoReplayModel, T as loadDemoData, U as entityViewEquals, V as getAreaViews, W as getAllEntityViews, X as setManagerConnection, Y as registerEntity, Z as setResubscribeHandler, _ as applyDemoServiceCall, a as fetchForecastData, b as demoCallLog, c as normalizeStatisticTime, d as callService, et as setState, f as sendCommand, g as updateEntity, h as turnOn, i as fetchForecast, j as demoAssetUrl, k as stopDemoEnergyTicker, l as batchEntityUpdates, m as turnOff, o as fetchForecasts, p as toggle, q as extractDomain, s as fetchStatisticsDuringPeriod, t as forceResubscribeCalendars, tt as state, u as batchServiceCalls, v as applyVisitorHolds, w as isDemoMode, x as demoModel, y as createDemoFixtures, z as buildDeviceView } from "./track-DssLNusE.js";
|
|
2
2
|
import { t as runHaBridgeWorker } from "./worker-main-B6eeHPDQ.js";
|
|
3
3
|
import { produce } from "solid-js/store";
|
|
4
4
|
//#region src/core/reducers.ts
|
|
@@ -995,6 +995,92 @@ function entityIdHistoryNeedsAttributes(entityId) {
|
|
|
995
995
|
return NEED_ATTRIBUTE_DOMAINS.includes(domain);
|
|
996
996
|
}
|
|
997
997
|
//#endregion
|
|
998
|
+
//#region src/demo/sim/history.ts
|
|
999
|
+
const DAY_MS = 864e5;
|
|
1000
|
+
const STEP_MS = 3e5;
|
|
1001
|
+
const TICK_WALL_MS = 1e3;
|
|
1002
|
+
/** Unix seconds, matching the energy branch's wire format (`synthesizeEnergyHistory`). */
|
|
1003
|
+
function toSeconds(ms) {
|
|
1004
|
+
return Math.round(ms / 1e3);
|
|
1005
|
+
}
|
|
1006
|
+
function pushPoint(track, point) {
|
|
1007
|
+
track.lastState = point.s;
|
|
1008
|
+
const last = track.points.at(-1);
|
|
1009
|
+
if (last && last.lu === point.lu) track.points[track.points.length - 1] = point;
|
|
1010
|
+
else track.points.push(point);
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Replays the demo house once from `startMs` to `endMs` (sim time) and reports each entity's state changes.
|
|
1014
|
+
* `toWallMs` stamps `lu` on the caller's clock.
|
|
1015
|
+
*/
|
|
1016
|
+
function demoHistory(entityIds, startMs, endMs, toWallMs = (ms) => ms) {
|
|
1017
|
+
const result = {};
|
|
1018
|
+
for (const id of entityIds) result[id] = [];
|
|
1019
|
+
const live = demoModel();
|
|
1020
|
+
if (!live) return result;
|
|
1021
|
+
const tracks = [];
|
|
1022
|
+
for (const entityId of new Set(entityIds)) {
|
|
1023
|
+
const device = live.deviceOf(entityId);
|
|
1024
|
+
if (device) tracks.push({
|
|
1025
|
+
entityId,
|
|
1026
|
+
deviceKey: device.key,
|
|
1027
|
+
points: [],
|
|
1028
|
+
lastState: void 0
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
if (tracks.length === 0) return result;
|
|
1032
|
+
const liveNowMs = live.nowMs;
|
|
1033
|
+
const endC = toWallMs(liveNowMs) - toWallMs(endMs) <= TICK_WALL_MS ? liveNowMs : endMs;
|
|
1034
|
+
const startC = Math.max(startMs, endC - DAY_MS);
|
|
1035
|
+
if (startC >= endC) return result;
|
|
1036
|
+
const log = demoCallLog();
|
|
1037
|
+
const first = log[0];
|
|
1038
|
+
const modelStartMs = first ? Math.min(startC, first.simMs) : startC;
|
|
1039
|
+
const replayModel = demoReplayModel(modelStartMs);
|
|
1040
|
+
if (!replayModel) return result;
|
|
1041
|
+
const replay = replayModel;
|
|
1042
|
+
function record(simMs) {
|
|
1043
|
+
if (simMs < startC) return;
|
|
1044
|
+
for (const track of tracks) {
|
|
1045
|
+
const p = replay.projectDevice(track.deviceKey)[track.entityId];
|
|
1046
|
+
if (!p || p.state === track.lastState) continue;
|
|
1047
|
+
pushPoint(track, {
|
|
1048
|
+
s: p.state,
|
|
1049
|
+
a: p.attributes,
|
|
1050
|
+
lu: toSeconds(toWallMs(simMs))
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
record(replay.nowMs);
|
|
1055
|
+
let logIdx = 0;
|
|
1056
|
+
while (replay.nowMs < endC) {
|
|
1057
|
+
const next = log[logIdx];
|
|
1058
|
+
const nextLogMs = next ? next.simMs : Number.POSITIVE_INFINITY;
|
|
1059
|
+
const windowBoundary = replay.nowMs < startC ? startC : Number.POSITIVE_INFINITY;
|
|
1060
|
+
const targetMs = Math.min(replay.nowMs + STEP_MS, endC, nextLogMs, windowBoundary);
|
|
1061
|
+
replay.advanceTo(targetMs, STEP_MS);
|
|
1062
|
+
record(replay.nowMs);
|
|
1063
|
+
if (next && next.simMs === replay.nowMs) {
|
|
1064
|
+
replay.dispatch(next.call);
|
|
1065
|
+
applyVisitorHolds(replay, next.call.entityIds);
|
|
1066
|
+
logIdx++;
|
|
1067
|
+
record(replay.nowMs);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
for (const track of tracks) {
|
|
1071
|
+
if (endC === liveNowMs) {
|
|
1072
|
+
const p = live.projectDevice(track.deviceKey)[track.entityId];
|
|
1073
|
+
if (p && p.state !== track.lastState) pushPoint(track, {
|
|
1074
|
+
s: p.state,
|
|
1075
|
+
a: p.attributes,
|
|
1076
|
+
lu: toSeconds(toWallMs(endC))
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
result[track.entityId] = track.points.length > 5760 ? track.points.slice(-MAX_HISTORY_POINTS) : track.points;
|
|
1080
|
+
}
|
|
1081
|
+
return result;
|
|
1082
|
+
}
|
|
1083
|
+
//#endregion
|
|
998
1084
|
//#region src/history/fetch.ts
|
|
999
1085
|
/**
|
|
1000
1086
|
* History Fetching
|
|
@@ -1006,18 +1092,19 @@ function entityIdHistoryNeedsAttributes(entityId) {
|
|
|
1006
1092
|
*/
|
|
1007
1093
|
async function fetchHistory(options) {
|
|
1008
1094
|
const { startTime, endTime, entityIds = [], includeStartTimeState = true, significantChangesOnly = true, minimalResponse = true, noAttributes: noAttributesOverride } = options;
|
|
1009
|
-
|
|
1010
|
-
|
|
1095
|
+
const timeMap = demoTimeMap();
|
|
1096
|
+
if (timeMap) {
|
|
1097
|
+
const startMs = timeMap.toSim(startTime.getTime());
|
|
1098
|
+
const endMs = timeMap.toSim((endTime ?? /* @__PURE__ */ new Date()).getTime());
|
|
1099
|
+
const energyStepMs = timeMap.toSim(6e4) - timeMap.toSim(0);
|
|
1100
|
+
const toWallSeconds = (simSeconds) => Math.round(timeMap.toWall(simSeconds * 1e3) / 1e3);
|
|
1101
|
+
const replayed = demoHistory(entityIds.filter((id) => !isEnergyEntity(id)), startMs, endMs, (ms) => timeMap.toWall(ms));
|
|
1011
1102
|
const result = {};
|
|
1012
|
-
for (const id of entityIds) {
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
a: {},
|
|
1018
|
-
lu: p.lu
|
|
1019
|
-
}));
|
|
1020
|
-
}
|
|
1103
|
+
for (const id of entityIds) result[id] = isEnergyEntity(id) ? synthesizeEnergyHistory(id, startMs, endMs, energyStepMs).map((p) => ({
|
|
1104
|
+
s: p.s,
|
|
1105
|
+
a: {},
|
|
1106
|
+
lu: toWallSeconds(p.lu)
|
|
1107
|
+
})) : replayed[id] ?? [];
|
|
1021
1108
|
return result;
|
|
1022
1109
|
}
|
|
1023
1110
|
const startTimeStr = startTime.toISOString();
|
|
@@ -1088,8 +1175,6 @@ function historyStateToTimeline(s) {
|
|
|
1088
1175
|
}
|
|
1089
1176
|
//#endregion
|
|
1090
1177
|
//#region src/history/query.ts
|
|
1091
|
-
/** Hard cap on retained points per entity timeline. */
|
|
1092
|
-
const MAX_HISTORY_POINTS = 5760;
|
|
1093
1178
|
/** Live tracker count per entity. Ref-counted because a timeline is shared: two
|
|
1094
1179
|
* widgets on the same entity must not let the first unmount delete the store
|
|
1095
1180
|
* data the second is still rendering (appendHistoryPoint would then silently
|
|
@@ -1120,64 +1205,6 @@ function untrackEntityHistory(entityId) {
|
|
|
1120
1205
|
delete s.history[entityId];
|
|
1121
1206
|
}));
|
|
1122
1207
|
}
|
|
1123
|
-
/**
|
|
1124
|
-
* Append a state change to an entity's history.
|
|
1125
|
-
* Called by the entity subscription handler when a tracked entity changes.
|
|
1126
|
-
*/
|
|
1127
|
-
function appendHistoryPoint(entityId, stateValue, attributes, lastUpdated, lastChanged) {
|
|
1128
|
-
setState(produce((s) => {
|
|
1129
|
-
const history = s.history[entityId];
|
|
1130
|
-
if (!history) return;
|
|
1131
|
-
const point = {
|
|
1132
|
-
s: stateValue,
|
|
1133
|
-
a: attributes,
|
|
1134
|
-
lu: lastUpdated,
|
|
1135
|
-
lc: lastChanged
|
|
1136
|
-
};
|
|
1137
|
-
history.entityHistory.push(point);
|
|
1138
|
-
history.timeline.push({
|
|
1139
|
-
timestamp: lastUpdated,
|
|
1140
|
-
state: stateValue,
|
|
1141
|
-
attributes,
|
|
1142
|
-
lastChanged,
|
|
1143
|
-
lastUpdated
|
|
1144
|
-
});
|
|
1145
|
-
}));
|
|
1146
|
-
}
|
|
1147
|
-
/**
|
|
1148
|
-
* Append multiple history points in a single setState(produce(...)).
|
|
1149
|
-
* Called by the rAF-batched subscription flush.
|
|
1150
|
-
*/
|
|
1151
|
-
function bulkAppendHistoryPoints(points) {
|
|
1152
|
-
if (points.length === 0) return;
|
|
1153
|
-
setState(produce((s) => {
|
|
1154
|
-
const touched = /* @__PURE__ */ new Set();
|
|
1155
|
-
for (const { entityId, stateValue, attributes, lastUpdated, lastChanged } of points) {
|
|
1156
|
-
const history = s.history[entityId];
|
|
1157
|
-
if (!history) continue;
|
|
1158
|
-
history.entityHistory.push({
|
|
1159
|
-
s: stateValue,
|
|
1160
|
-
a: attributes,
|
|
1161
|
-
lu: lastUpdated,
|
|
1162
|
-
lc: lastChanged
|
|
1163
|
-
});
|
|
1164
|
-
history.timeline.push({
|
|
1165
|
-
timestamp: lastUpdated,
|
|
1166
|
-
state: stateValue,
|
|
1167
|
-
attributes,
|
|
1168
|
-
lastChanged,
|
|
1169
|
-
lastUpdated
|
|
1170
|
-
});
|
|
1171
|
-
touched.add(entityId);
|
|
1172
|
-
}
|
|
1173
|
-
for (const entityId of touched) {
|
|
1174
|
-
const history = s.history[entityId];
|
|
1175
|
-
if (!history) continue;
|
|
1176
|
-
if (history.entityHistory.length > 5760) history.entityHistory.splice(0, history.entityHistory.length - MAX_HISTORY_POINTS);
|
|
1177
|
-
if (history.timeline.length > 5760) history.timeline.splice(0, history.timeline.length - MAX_HISTORY_POINTS);
|
|
1178
|
-
}
|
|
1179
|
-
}));
|
|
1180
|
-
}
|
|
1181
1208
|
//#endregion
|
|
1182
1209
|
//#region src/weather/query.ts
|
|
1183
1210
|
/**
|
|
@@ -1811,7 +1838,7 @@ function detachBridgeFromStore() {
|
|
|
1811
1838
|
* host's link with one the widget controls — every subsequent service call is
|
|
1812
1839
|
* intercepted and every entity the dashboard renders can be fabricated.
|
|
1813
1840
|
* - disconnect / detachBridgeFromStore: drop the household's connection.
|
|
1814
|
-
* - loadDemoData / unloadDemoData: overwrite live state with
|
|
1841
|
+
* - loadDemoData / loadDemoHouse / resetDemo / unloadDemoData: overwrite live state with the demo house.
|
|
1815
1842
|
*/
|
|
1816
1843
|
let unclaimed = {
|
|
1817
1844
|
attachBridgeToStore,
|
|
@@ -1821,6 +1848,8 @@ let unclaimed = {
|
|
|
1821
1848
|
createHaBridge,
|
|
1822
1849
|
disconnect,
|
|
1823
1850
|
loadDemoData,
|
|
1851
|
+
loadDemoHouse,
|
|
1852
|
+
resetDemo,
|
|
1824
1853
|
unloadDemoData
|
|
1825
1854
|
};
|
|
1826
1855
|
/**
|
package/dist/solid/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as getEntityView, Q as privilegedConn, R as buildAreaView, U as entityViewEquals, V as getAreaViews, Y as registerEntity, d as callService, et as setState, h as turnOn, m as turnOff, n as trackCalendarEvents, p as toggle, q as extractDomain, r as buildDemoForecast, s as fetchStatisticsDuringPeriod, tt as state, w as isDemoMode } from "../track-DssLNusE.js";
|
|
2
2
|
import { produce } from "solid-js/store";
|
|
3
3
|
import { createEffect, createMemo, createResource, onCleanup } from "solid-js";
|
|
4
4
|
//#region src/weather/track.ts
|