mirror of
https://github.com/home-assistant/frontend.git
synced 2026-10-10 07:05:45 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81a6d4bcdd |
@@ -60,7 +60,7 @@ const generateSumStatistics = (
|
||||
end: Date,
|
||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||
initValue: number,
|
||||
maxDiff: number | ((start: Date, end: Date) => number)
|
||||
maxDiff: number
|
||||
): StatisticValue[] => {
|
||||
const statistics: StatisticValue[] = [];
|
||||
let currentDate = new Date(start);
|
||||
@@ -69,9 +69,7 @@ const generateSumStatistics = (
|
||||
const now = new Date();
|
||||
while (end > currentDate && currentDate < now) {
|
||||
const nextDate = getNextDate(currentDate, period);
|
||||
const bound =
|
||||
typeof maxDiff === "function" ? maxDiff(currentDate, nextDate) : maxDiff;
|
||||
const add = Math.random() * bound;
|
||||
const add = Math.random() * maxDiff;
|
||||
sum += add;
|
||||
statistics.push({
|
||||
start: currentDate.getTime(),
|
||||
@@ -138,15 +136,6 @@ const statisticsFunctions: Record<
|
||||
period: "5minute" | "hour" | "day" | "month"
|
||||
) => StatisticValue[]
|
||||
> = {
|
||||
"sensor.energy_water": (_id, start, end, period = "hour") =>
|
||||
generateSumStatistics(
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
4000,
|
||||
(bucketStart, bucketEnd) =>
|
||||
(20 * (bucketEnd.getTime() - bucketStart.getTime())) / 3600000
|
||||
),
|
||||
"sensor.energy_consumption_tarif_1": (
|
||||
_id: string,
|
||||
start: Date,
|
||||
@@ -312,11 +301,6 @@ const statisticsFunctions: Record<
|
||||
return [...morning, ...production, ...evening, ...rest];
|
||||
},
|
||||
};
|
||||
// Prices are per source unit; water uses litres (4 currency units per m³).
|
||||
const derivedCosts: Record<string, { source: string; price: number }> = {
|
||||
"sensor.energy_water_cost": { source: "sensor.energy_water", price: 0.004 },
|
||||
};
|
||||
|
||||
export const mockRecorder = (mockHass: MockHomeAssistant) => {
|
||||
mockHass.mockWS(
|
||||
"recorder/get_statistics_metadata",
|
||||
@@ -333,23 +317,10 @@ export const mockRecorder = (mockHass: MockHomeAssistant) => {
|
||||
const end = end_time ? new Date(end_time) : new Date();
|
||||
|
||||
const statistics: Record<string, StatisticValue[]> = {};
|
||||
const cache: Record<string, StatisticValue[]> = {};
|
||||
const getStats = (id: string) => {
|
||||
cache[id] ??= statisticsFunctions[id](id, start, end, period);
|
||||
return cache[id];
|
||||
};
|
||||
|
||||
statistic_ids.forEach((id: string) => {
|
||||
if (id in derivedCosts) {
|
||||
const { source, price } = derivedCosts[id];
|
||||
let cost = 0;
|
||||
statistics[id] = getStats(source).map((statistic) => {
|
||||
const change = statistic.change! * price;
|
||||
cost += change;
|
||||
return { ...statistic, change, state: cost, sum: cost };
|
||||
});
|
||||
} else if (id in statisticsFunctions) {
|
||||
statistics[id] = getStats(id);
|
||||
if (id in statisticsFunctions) {
|
||||
statistics[id] = statisticsFunctions[id](id, start, end, period);
|
||||
} else {
|
||||
const entityState = hass.states[id];
|
||||
const state = entityState ? Number(entityState.state) : 1;
|
||||
|
||||
+3
-3
@@ -85,7 +85,7 @@
|
||||
"@swc/helpers": "0.5.23",
|
||||
"@tsparticles/engine": "4.4.0",
|
||||
"@tsparticles/preset-links": "4.4.0",
|
||||
"@versatiles/style": "6.3.0",
|
||||
"@versatiles/style": "6.2.0",
|
||||
"@vibrant/color": "4.0.4",
|
||||
"@vvo/tzdb": "6.198.0",
|
||||
"@webcomponents/scoped-custom-element-registry": "0.0.10",
|
||||
@@ -113,7 +113,7 @@
|
||||
"lit": "3.3.3",
|
||||
"lit-html": "3.3.3",
|
||||
"luxon": "3.7.2",
|
||||
"maplibre-gl": "6.13.0",
|
||||
"maplibre-gl": "6.12.0",
|
||||
"marked": "18.1.0",
|
||||
"memoize-one": "6.0.0",
|
||||
"nanoid": "6.0.2",
|
||||
@@ -225,7 +225,7 @@
|
||||
"webpackbar": "7.0.0",
|
||||
"workbox-build": "7.4.1"
|
||||
},
|
||||
"packageManager": "[email protected].1",
|
||||
"packageManager": "[email protected].0",
|
||||
"volta": {
|
||||
"node": "24.21.0"
|
||||
}
|
||||
|
||||
Generated
+79
-79
@@ -7,153 +7,153 @@ importers:
|
||||
configDependencies: {}
|
||||
packageManagerDependencies:
|
||||
pnpm:
|
||||
specifier: 12.10.1
|
||||
version: 12.10.1
|
||||
specifier: 12.10.0
|
||||
version: 12.10.0
|
||||
|
||||
packages:
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-CVTlHPwNvadQCJD9bGSMzWIhFX8QpjtqC2c27dhdnn/9iKzEjZ3qL62o3gHpKbIuo6qn4WxTKRoaokgNdReBig==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-QMMRzOI/7CU4xLbKY6O2BZn3VI4+a8LLyim18H7it8llBWuBPMqDqUURE8045k+7lI8/lI2/tElhyKptEviKDQ==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-NFiYLIaodY7da0XIebwcU3JoP7IK/lzF7zgKSSP+9H+QcFnQ1GDfBkuBKCYJzZ+Xu0WH54neIPLBBCaOjaaauA==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-41zwlROW+t523Nfqo4rWp8IPiSK5vnAWrnCey26Je45rX1SMNc4ABY7OFmPw41/t+Y0CE+4tjTj+0s9YGqPM5w==}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-0O8tdQ8ijlPJudXspLMTcitMkdBEz6uUflazL5uQE0WMs85oQIp0U+5hfEktMFB64QqEhjqlvvujTwbzdr9oMg==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-L+r7AD8Fjf8Vcc4ZRJl+Pjzc27CIeQ/FiRwPmOluFO2UcXubmGHdW+OuMUxrU0vkoXiGR61Ft0RtaPwTRY4W/g==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-ud+1/uZOKEo8P/AsPynOJc/LNwfI0j6WwCElibj71rU9l4nIBnsSn+wWTIPZPkZ4BBSH5+82azSnAARMyJ1lNA==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-/TCF1K6E+4PnbkLgqGS1Iqlf5bHp6FDzuXgu6++PMMAFkF7Yk5EF3BcfG1gYYjpkvlJBccvVMsRBnWFbSyqu1w==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-mj9PE5rf8uAfQQ2K66HSATMSut+lNiB4eSqFd5+azFVCMnxNSy/32xpZQJT21PhnN3Y4qbK+iKHe5nWAxSuRhw==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-k7/WFA91E2qhnR/2EOEv402U8bjP758y2pybbdiB5Hrd4KhgviVOJp5cFrXpKgd8HZJs/RZN7cdmMvU2Q2BVgg==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-xba+00wZJ8Um6rBJJjWl88uJj0tydB8dtomvjlCLvi0uL32vpa9CRP8Vv26FIXvbiZ1bo2RCzYt/eChxJVV52w==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-ChD8bN0lRCRaL+CMOaMUgZQ4WHzEkDXmDHrZgXgdoo6yymQKKzr66Ic7Sl/D7Ky1cVUcFEzHjlq4fGDJwt6Lqg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-oBdMp69ScC9UnniG4qZAQVr2fBDSXjm4yk/72vkEVyrlwS23yMxcRQl7Qdo3sgXPAygY6TWnPRKm4rXzjoyW7w==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-egl5RUSQFh7kETBdmMhaTuaQKP1pjH6Cxq370zgpFFKJXF+GGkIzK+jLNazrjX9pKIWF3iqn7kUeyP6yKxzBoA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-Yyb3wu09h3c7mLme270uHFiVaAIUHC411Ru9LIU2BKUIstrGlXa9OqqVWoXaRgYRdFdOFknkwG7GNn6ygwLbnw==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-YJ6bEZ+stPpv71CGfGQQeyIpMx/zSMEcAXQzG+rjBtzVfyNsxYciRevhJ+PE9b2qKqN78Mh/1tOMmx9ly4VXGw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-PdkeUFFkybknnGkWP0H22eMpIiS4OZXL5BcQzF4lh+vmrW3IaC2HOkbANKgot/PKO0Kl77pzA/6PKFxgbgfXIQ==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-njfd4euctC1zH1nVBbm6+r1c+0y/TtgqN523rk/KMSxqItpV5QAVa9Yz48Rt5DOIKmuLq7xXOhsQodBlbTk3pw==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-1okKuHKJwJPAbofDxfhZWAUxEWtee4ZSf7Pah8kcvocaJkf2WxFJ5KVTiNIvDml5GLidDQsgf7Pcf/WHbCak7Q==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-4JI2F8pYGMcsG6ny61OiBSvZeDozc64TbPozbTU2X5uCsaFCsCvcpr/WwyypwCv+/mNjcIhaKhlxpwJYsnteIg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-e6IqzVNkPa7srFKJKnY23uWJ+qz0LaRWiTUo/sHfFXRRMRzB5uNOr6qWWip/jqhdGwU91n9J7LrEYZ6e0tRczw==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-xayd2iG8ugdvjlGeOvsfm+iSe0bFu9RTX3/8HWOLAQmHdbLKi4hPbxP0S4c9tj8pNej/IxVBQLJksRXFlhNjPw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-ZByV0DRgWzGaDSjT5ddRBASdwz+r/qPMYh7o6RGmPQjtRGNFbSl94xY2DcAM8mqCOZJUUDtAXQ+wpBXcdpKlkg==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-PFkzWEghFLKuocxMHtn57mlJ59f5aBbqjX6FCUtiunEHqxTxOibSduQPs3Llm6VWbAXBjD3VrX29Z+bjU1Dpyw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-I7QZHcjioG7orFeCRUFUHByJ1G0zFPnAlaGGyrUvb6MGkv5oeNwNPl7t+Gp+7zHfnMcgLGJ1a+Wfim0IDw3lOw==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-0HtTS+TLONWd/dNSczyOkK0UeZ36cbdhC/2ljZ61DPhvc4jTb7ur0yU47On0in7Im3yXwzTY4vtF8ykrDwc+NQ==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
resolution: {integrity: sha512-4WJFdp58EKlCj0zLobrXU0vpszSZIr4X/3y/uNbAQqGW0zE+VdruZB0gFc3L2kzsUzVwTYbaCn+XEhnCYSAlTg==}
|
||||
'@pnpm/[email protected].0':
|
||||
resolution: {integrity: sha512-IcW3rehTGzJ7YnmHEWnbnJakjbBmnH0r29qiajK9+6b9psMF9IjocFr0dyitRVSfXxyW/FI5PIK3mOswGoyFTg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
[email protected].1:
|
||||
resolution: {integrity: sha512-ukCjfrGjcNYP6oxM8dNkwTvMzvUY6YrSvO6VT1OdONo3RY5YJho/pV4GUjRQ6g//+fSXsTW+QfLBXBZCusrObA==}
|
||||
[email protected].0:
|
||||
resolution: {integrity: sha512-Eip7bd+dQCaLwNsal4CJm5Xk+out/Ke9RQYVrYz3wmWfX1acIO18U4hrx7CNDVClT0rVBwaEf1aC7GxQSEFlOQ==}
|
||||
engines: {node: '>=18.*'}
|
||||
hasBin: true
|
||||
|
||||
snapshots:
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
'@pnpm/[email protected].1':
|
||||
'@pnpm/[email protected].0':
|
||||
optional: true
|
||||
|
||||
[email protected].1:
|
||||
[email protected].0:
|
||||
optionalDependencies:
|
||||
'@pnpm/exe.android-arm64': 12.10.1
|
||||
'@pnpm/exe.android-x64': 12.10.1
|
||||
'@pnpm/exe.darwin-arm64': 12.10.1
|
||||
'@pnpm/exe.darwin-x64': 12.10.1
|
||||
'@pnpm/exe.freebsd-x64': 12.10.1
|
||||
'@pnpm/exe.linux-arm64': 12.10.1
|
||||
'@pnpm/exe.linux-arm64-musl': 12.10.1
|
||||
'@pnpm/exe.linux-ppc64': 12.10.1
|
||||
'@pnpm/exe.linux-riscv64': 12.10.1
|
||||
'@pnpm/exe.linux-s390x': 12.10.1
|
||||
'@pnpm/exe.linux-x64': 12.10.1
|
||||
'@pnpm/exe.linux-x64-musl': 12.10.1
|
||||
'@pnpm/exe.win32-arm64': 12.10.1
|
||||
'@pnpm/exe.win32-x64': 12.10.1
|
||||
'@pnpm/exe.android-arm64': 12.10.0
|
||||
'@pnpm/exe.android-x64': 12.10.0
|
||||
'@pnpm/exe.darwin-arm64': 12.10.0
|
||||
'@pnpm/exe.darwin-x64': 12.10.0
|
||||
'@pnpm/exe.freebsd-x64': 12.10.0
|
||||
'@pnpm/exe.linux-arm64': 12.10.0
|
||||
'@pnpm/exe.linux-arm64-musl': 12.10.0
|
||||
'@pnpm/exe.linux-ppc64': 12.10.0
|
||||
'@pnpm/exe.linux-riscv64': 12.10.0
|
||||
'@pnpm/exe.linux-s390x': 12.10.0
|
||||
'@pnpm/exe.linux-x64': 12.10.0
|
||||
'@pnpm/exe.linux-x64-musl': 12.10.0
|
||||
'@pnpm/exe.win32-arm64': 12.10.0
|
||||
'@pnpm/exe.win32-x64': 12.10.0
|
||||
|
||||
---
|
||||
lockfileVersion: '9.0'
|
||||
@@ -294,7 +294,7 @@ importers:
|
||||
version: 1.0.3
|
||||
'@maplibre/maplibre-gl-leaflet':
|
||||
specifier: 0.1.4
|
||||
version: 0.1.4(@types/[email protected])([email protected])([email protected]3.0)
|
||||
version: 0.1.4(@types/[email protected])([email protected])([email protected]2.0)
|
||||
'@material/mwc-list':
|
||||
specifier: 0.27.0
|
||||
version: 0.27.0(patch_hash=9450e509a86887d8f68ca9cf3f81e6ed70e94e49de13c5f6f20f94519ad4a987)
|
||||
@@ -317,8 +317,8 @@ importers:
|
||||
specifier: 4.4.0
|
||||
version: 4.4.0
|
||||
'@versatiles/style':
|
||||
specifier: 6.3.0
|
||||
version: 6.3.0([email protected]3.0)
|
||||
specifier: 6.2.0
|
||||
version: 6.2.0([email protected]2.0)
|
||||
'@vibrant/color':
|
||||
specifier: 4.0.4
|
||||
version: 4.0.4
|
||||
@@ -401,8 +401,8 @@ importers:
|
||||
specifier: 3.7.2
|
||||
version: 3.7.2
|
||||
maplibre-gl:
|
||||
specifier: 6.13.0
|
||||
version: 6.13.0
|
||||
specifier: 6.12.0
|
||||
version: 6.12.0
|
||||
marked:
|
||||
specifier: 18.1.0
|
||||
version: 18.1.0
|
||||
@@ -2260,8 +2260,8 @@ packages:
|
||||
'@mapbox/[email protected]':
|
||||
resolution: {integrity: sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q==}
|
||||
|
||||
'@maplibre/[email protected].2':
|
||||
resolution: {integrity: sha512-2ZYhobdAY+y4/P/z1xe0698165LywD0yDdWugdu3NRUrajgVWut+tLkcz7i/RJguMTURwK7gxwmwYMFJbgbQFw==}
|
||||
'@maplibre/[email protected].1':
|
||||
resolution: {integrity: sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==}
|
||||
|
||||
'@maplibre/[email protected]':
|
||||
resolution: {integrity: sha512-k57wcndZIvq3m08g2je4pjUPGr43ffNW3j+gXbymt8Vi2l1lUERUi1UmdTZcTPN8LuDDYOMWRNBaSLwpAu02ew==}
|
||||
@@ -3693,8 +3693,8 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@versatiles/style@6.3.0':
|
||||
resolution: {integrity: sha512-jJvt1ur0JQqeuFLLyIk8bw/G8t5ix5oGcf1gvOT4XCJs3zi8ZJ5VsSptpghany/vnOw5l8+5f9OQCFcTreY/sQ==}
|
||||
'@versatiles/style@6.2.0':
|
||||
resolution: {integrity: sha512-JsSHgu+rKvqIOjWp08WHQbfwCWU0XPeQbGCxHglm+j2K0oRyK41HP3V6jc0rAFKuqLK9p9/K0NBETLK7ZQarlQ==}
|
||||
engines: {node: '>=20'}
|
||||
peerDependencies:
|
||||
maplibre-gl: '>=5.0.0'
|
||||
@@ -5911,8 +5911,8 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==}
|
||||
|
||||
[email protected]3.0:
|
||||
resolution: {integrity: sha512-ELXk4h+xl0URFQEnVbAN6MGn61P6jq4amUWHiskLVsvHCaKdf1Zq6G8UNOD0AQ3UaXoL5ECc8ovz8yqYEBGPKw==}
|
||||
[email protected]2.0:
|
||||
resolution: {integrity: sha512-DwgganVi2BhNxOpD7ob3lJC0dQQz4HfJfuQQV3XxCY3XdOzFrMqp9ylMXhRzryRsOnIezdZcklWXIIs/Q8JPjA==}
|
||||
engines: {node: '>=16.14.0', npm: '>=8.1.0'}
|
||||
|
||||
[email protected]:
|
||||
@@ -9780,15 +9780,15 @@ snapshots:
|
||||
'@types/geojson': 7946.0.16
|
||||
pbf: 5.1.2
|
||||
|
||||
'@maplibre/[email protected].2':
|
||||
'@maplibre/[email protected].1':
|
||||
dependencies:
|
||||
kdbush: 4.1.0
|
||||
|
||||
'@maplibre/[email protected](@types/[email protected])([email protected])([email protected]3.0)':
|
||||
'@maplibre/[email protected](@types/[email protected])([email protected])([email protected]2.0)':
|
||||
dependencies:
|
||||
'@types/leaflet': 1.9.22
|
||||
leaflet: 1.9.4
|
||||
maplibre-gl: 6.13.0
|
||||
maplibre-gl: 6.12.0
|
||||
|
||||
'@maplibre/[email protected]':
|
||||
dependencies:
|
||||
@@ -11280,11 +11280,11 @@ snapshots:
|
||||
'@unrs/[email protected]':
|
||||
optional: true
|
||||
|
||||
'@versatiles/style@6.3.0([email protected]3.0)':
|
||||
'@versatiles/style@6.2.0([email protected]2.0)':
|
||||
dependencies:
|
||||
'@maplibre/maplibre-gl-style-spec': 26.4.4
|
||||
optionalDependencies:
|
||||
maplibre-gl: 6.13.0
|
||||
maplibre-gl: 6.12.0
|
||||
|
||||
'@vibrant/[email protected]': {}
|
||||
|
||||
@@ -13657,13 +13657,13 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]3.0:
|
||||
[email protected]2.0:
|
||||
dependencies:
|
||||
'@mapbox/point-geometry': 1.1.0
|
||||
'@mapbox/tiny-sdf': 2.2.0
|
||||
'@mapbox/unitbezier': 1.0.0
|
||||
'@mapbox/vector-tile': 3.0.0
|
||||
'@maplibre/geojson-vt': 6.1.2
|
||||
'@maplibre/geojson-vt': 6.1.1
|
||||
'@maplibre/maplibre-gl-style-spec': 26.4.4
|
||||
'@maplibre/mlt': 1.3.0
|
||||
'@maplibre/vt-pbf': 4.3.2
|
||||
|
||||
@@ -383,6 +383,8 @@ export class HuiEnergySourcesTableCard
|
||||
|
||||
let totalGrid = 0;
|
||||
let totalGridCost = 0;
|
||||
let gridImportIdx = 0;
|
||||
let gridExportIdx = 0;
|
||||
let totalBattery = 0;
|
||||
|
||||
let hasGridCost = false;
|
||||
@@ -774,9 +776,10 @@ export class HuiEnergySourcesTableCard
|
||||
)
|
||||
: ""
|
||||
}
|
||||
${types.grid?.map((source, idx) => {
|
||||
${types.grid?.map((source) => {
|
||||
const importResult = (() => {
|
||||
if (!source.stat_energy_from) return nothing;
|
||||
const idx = gridImportIdx++;
|
||||
|
||||
const cost_stat =
|
||||
source.stat_cost ||
|
||||
@@ -831,6 +834,7 @@ export class HuiEnergySourcesTableCard
|
||||
|
||||
const exportResult = (() => {
|
||||
if (!source.stat_energy_to) return nothing;
|
||||
const idx = gridExportIdx++;
|
||||
|
||||
const cost_stat =
|
||||
source.stat_compensation ||
|
||||
|
||||
@@ -326,15 +326,6 @@ export class HuiEnergyUsageGraphCard
|
||||
from_battery: {},
|
||||
};
|
||||
|
||||
// Grid sources can be import-only or export-only; assign color indices by
|
||||
// position in the user's grid sources config so this card matches the
|
||||
// energy sources table, which uses positional indices.
|
||||
const colorIndices: Record<string, Record<string, number>> = {};
|
||||
Object.keys(colorPropertyMap).forEach((key) => {
|
||||
colorIndices[key] = {};
|
||||
});
|
||||
let gridIdx = 0;
|
||||
|
||||
for (const source of energyData.prefs.energy_sources) {
|
||||
if (source.type === "solar") {
|
||||
if (statIds.solar) {
|
||||
@@ -378,7 +369,6 @@ export class HuiEnergyUsageGraphCard
|
||||
} else {
|
||||
statIds.from_grid = [gridSource.stat_energy_from];
|
||||
}
|
||||
colorIndices.from_grid[gridSource.stat_energy_from] = gridIdx;
|
||||
if (gridSource.name) {
|
||||
statLabels.from_grid[gridSource.stat_energy_from] =
|
||||
gridSource.stat_energy_to
|
||||
@@ -395,7 +385,6 @@ export class HuiEnergyUsageGraphCard
|
||||
} else {
|
||||
statIds.to_grid = [gridSource.stat_energy_to];
|
||||
}
|
||||
colorIndices.to_grid[gridSource.stat_energy_to] = gridIdx;
|
||||
if (gridSource.name) {
|
||||
statLabels.to_grid[gridSource.stat_energy_to] =
|
||||
gridSource.stat_energy_from
|
||||
@@ -406,18 +395,17 @@ export class HuiEnergyUsageGraphCard
|
||||
: gridSource.name;
|
||||
}
|
||||
}
|
||||
gridIdx++;
|
||||
}
|
||||
|
||||
const computedStyles = getComputedStyle(this);
|
||||
|
||||
const colorIndices: Record<string, Record<string, number>> = {};
|
||||
Object.keys(colorPropertyMap).forEach((key) => {
|
||||
colorIndices[key] = {};
|
||||
if (
|
||||
key === "used_grid" ||
|
||||
key === "used_solar" ||
|
||||
key === "used_battery" ||
|
||||
key === "from_grid" ||
|
||||
key === "to_grid"
|
||||
key === "used_battery"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ const TIMESTAMP_STATE_PROPS = ["last_updated", "last_changed"];
|
||||
|
||||
const TIMESTAMP_CONTENTS = [...TIMESTAMP_STATE_PROPS, "last_triggered"];
|
||||
|
||||
const TIMESTAMP_DOMAIN_CONTENTS: Record<string, string[] | undefined> = {
|
||||
const TIMESTAMP_DOMAIN_CONTENTS = {
|
||||
calendar: ["start_time", "end_time"],
|
||||
input_datetime: ["timestamp"],
|
||||
sun: [
|
||||
@@ -106,11 +106,10 @@ export const stateContentHasTimestamp = (
|
||||
}
|
||||
}
|
||||
}
|
||||
const domainContents = TIMESTAMP_DOMAIN_CONTENTS[domain];
|
||||
return (
|
||||
!!content &&
|
||||
!!domainContents &&
|
||||
contentArray.some((c) => domainContents.includes(c))
|
||||
TIMESTAMP_DOMAIN_CONTENTS[domain] &&
|
||||
content &&
|
||||
contentArray.some((c) => TIMESTAMP_DOMAIN_CONTENTS[domain].includes(c))
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { mockRecorder } from "../../demo/src/stubs/recorder";
|
||||
import type { Statistics } from "../../src/data/recorder";
|
||||
import type { MockHomeAssistant } from "../../src/fake_data/provide_hass";
|
||||
|
||||
const fetchWater = (
|
||||
period: "5minute" | "hour" | "day" | "month",
|
||||
ids = ["sensor.energy_water", "sensor.energy_water_cost"],
|
||||
start = "2026-01-01T00:00:00Z",
|
||||
end = "2026-02-01T00:00:00Z"
|
||||
): Statistics => {
|
||||
const mockWS = vi.fn();
|
||||
const hass = { mockWS, states: {} } as unknown as MockHomeAssistant;
|
||||
mockRecorder(hass);
|
||||
const handler = mockWS.mock.calls.find(
|
||||
([type]) => type === "recorder/statistics_during_period"
|
||||
)![1];
|
||||
return handler(
|
||||
{
|
||||
statistic_ids: ids,
|
||||
start_time: start,
|
||||
end_time: end,
|
||||
period,
|
||||
},
|
||||
hass
|
||||
);
|
||||
};
|
||||
|
||||
describe("demo water statistics", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date("2026-03-01T00:00:00Z"));
|
||||
vi.spyOn(Math, "random").mockReturnValue(0.5);
|
||||
});
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it.each([
|
||||
["5minute", 20 / 24],
|
||||
["hour", 10],
|
||||
["day", 240],
|
||||
["month", 7440],
|
||||
] as const)("scales consumption for %s buckets", (period, expected) => {
|
||||
expect(fetchWater(period)["sensor.energy_water"][0].change).toBeCloseTo(
|
||||
expected
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["2026-02-01", "2026-03-01", 6720],
|
||||
["2024-02-01", "2024-03-01", 6960],
|
||||
["2026-04-01", "2026-05-01", 7200],
|
||||
])("uses the actual month duration from %s", (start, end, expected) => {
|
||||
vi.setSystemTime(new Date("2027-01-01T00:00:00Z"));
|
||||
const stats = fetchWater(
|
||||
"month",
|
||||
undefined,
|
||||
`${start}T00:00:00Z`,
|
||||
`${end}T00:00:00Z`
|
||||
);
|
||||
expect(stats["sensor.energy_water"][0].change).toBeCloseTo(expected);
|
||||
});
|
||||
|
||||
it("scales each month independently in a multi-month request", () => {
|
||||
vi.setSystemTime(new Date("2027-01-01T00:00:00Z"));
|
||||
const stats = fetchWater(
|
||||
"month",
|
||||
undefined,
|
||||
"2026-01-01T00:00:00Z",
|
||||
"2026-04-01T00:00:00Z"
|
||||
);
|
||||
expect(stats["sensor.energy_water"].map((bucket) => bucket.change)).toEqual(
|
||||
[7440, 6720, 7440]
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["sensor.energy_water", "sensor.energy_water_cost"],
|
||||
["sensor.energy_water_cost", "sensor.energy_water"],
|
||||
["sensor.energy_water_cost"],
|
||||
])("derives costs regardless of requested IDs: %j", (...ids) => {
|
||||
vi.spyOn(Math, "random").mockReturnValueOnce(0.25).mockReturnValue(0.5);
|
||||
const stats = fetchWater("hour", ids);
|
||||
const costs = stats["sensor.energy_water_cost"];
|
||||
expect(costs[0].change).toBeCloseTo(5 * 0.004);
|
||||
let total = 0;
|
||||
costs.forEach((cost, index) => {
|
||||
const consumption = stats["sensor.energy_water"]?.[index];
|
||||
if (consumption) {
|
||||
expect(cost.change).toBeCloseTo(consumption.change! * 0.004);
|
||||
}
|
||||
total += cost.change!;
|
||||
expect(cost.sum).toBeCloseTo(total);
|
||||
expect(cost.state).toBeCloseTo(total);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user