@camstack/addon-provider-homeassistant 1.2.142 → 1.2.144
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/addon.js +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/{dist-1gj-XZ-R.js → dist-BwQbmKRC.js} +1603 -1050
- package/dist/{dist-DbcraPOl.mjs → dist-CzKKAmb9.mjs} +1603 -1050
- package/dist/ha-export/ha-export.addon.js +22 -8
- package/dist/ha-export/ha-export.addon.mjs +22 -8
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
//#endregion
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-BwQbmKRC.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
//#region src/ha-export/topics.ts
|
|
9
9
|
/**
|
|
@@ -2872,6 +2872,10 @@ var CAPS_NOT_EXPORTED = [
|
|
|
2872
2872
|
cap: "videoclips",
|
|
2873
2873
|
reason: "Media retrieval by handle, not a state. Clips reach the operator through notifications and the viewer."
|
|
2874
2874
|
},
|
|
2875
|
+
{
|
|
2876
|
+
cap: "recording",
|
|
2877
|
+
reason: "Since D625 this is the per-camera COVERAGE and PLAYBACK collection: which sources a camera has recordings in, what each covers over a window, and how to play an instant of it. Every method takes a window and a chosen source, so nothing here is a state a descriptor could publish — an entity would have to invent both. What an operator actually wants in Home Assistant is \"is this camera recording\", and that is `RecordingConfig.enabled` on `recording-archive`, which the camera-function switches already export as the ONE authority (D62). A second entity over this cap would be the second knob that decision forbids."
|
|
2878
|
+
},
|
|
2875
2879
|
{
|
|
2876
2880
|
cap: "webrtc-session",
|
|
2877
2881
|
reason: "A session opener — the definition of transport."
|
|
@@ -4038,8 +4042,8 @@ async function applyCameraFunctionWrite(api, deviceId, write, sourceNodeId) {
|
|
|
4038
4042
|
});
|
|
4039
4043
|
return;
|
|
4040
4044
|
case "recording-enabled": {
|
|
4041
|
-
const config = await api.
|
|
4042
|
-
await api.
|
|
4045
|
+
const config = await api.recordingArchive.getDeviceConfig.query({ deviceId });
|
|
4046
|
+
await api.recordingArchive.setDeviceConfig.mutate({
|
|
4043
4047
|
deviceId,
|
|
4044
4048
|
config: {
|
|
4045
4049
|
...config,
|
|
@@ -4934,9 +4938,11 @@ function projectMotion(deviceKey, input) {
|
|
|
4934
4938
|
/**
|
|
4935
4939
|
* A clearing edge carries no timestamp. `last_detection` answers "when
|
|
4936
4940
|
* did something last happen", and restamping it when nothing happened
|
|
4937
|
-
* makes an idle camera look permanently busy.
|
|
4941
|
+
* makes an idle camera look permanently busy. Same for a detection whose
|
|
4942
|
+
* timestamp is unknown or implausible — omitted rather than published as
|
|
4943
|
+
* a lie the automation author would trust.
|
|
4938
4944
|
*/
|
|
4939
|
-
if (input.detected) values.push({
|
|
4945
|
+
if (input.detected && input.timestamp !== null) values.push({
|
|
4940
4946
|
topic: stateTopic(deviceKey, "motion_last_detection"),
|
|
4941
4947
|
value: iso(input.timestamp)
|
|
4942
4948
|
});
|
|
@@ -5926,6 +5932,13 @@ var PUSH_PATH = "/api/camstack/push";
|
|
|
5926
5932
|
var MEDIA_ROUTE_PREFIX = `/addon/${ADDON_ID}/ha-media`;
|
|
5927
5933
|
/** How long `doorbell_pressed` stays on before its OFF edge is published. */
|
|
5928
5934
|
var DOORBELL_PULSE_MS = 5e3;
|
|
5935
|
+
/**
|
|
5936
|
+
* The earliest timestamp a real change could plausibly carry. Below this,
|
|
5937
|
+
* a slice field is a placeholder or a seeded "known value, unknown change
|
|
5938
|
+
* time" stamp (e.g. Homematic's `HM_SEEDED_CHANGED_AT = 1`) — never a real
|
|
5939
|
+
* instant. Year 2000 predates every device this addon exports.
|
|
5940
|
+
*/
|
|
5941
|
+
var MIN_PLAUSIBLE_TIMESTAMP_MS = Date.UTC(2e3, 0, 1);
|
|
5929
5942
|
/** The hub's API port — where the data plane is reverse-proxied. */
|
|
5930
5943
|
var HUB_API_PORT = 4443;
|
|
5931
5944
|
/** One PTZ button press, as a relative move. */
|
|
@@ -6228,9 +6241,10 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
6228
6241
|
const detected = slice["detected"];
|
|
6229
6242
|
const lastDetectedAt = readNumber(slice, "lastDetectedAt");
|
|
6230
6243
|
if (typeof detected !== "boolean") return;
|
|
6244
|
+
const timestamp = lastDetectedAt === null ? Date.now() : lastDetectedAt >= MIN_PLAUSIBLE_TIMESTAMP_MS ? lastDetectedAt : null;
|
|
6231
6245
|
this.push(deviceId, projectMotion(deviceKey, {
|
|
6232
6246
|
detected,
|
|
6233
|
-
timestamp
|
|
6247
|
+
timestamp
|
|
6234
6248
|
}));
|
|
6235
6249
|
}
|
|
6236
6250
|
}
|
|
@@ -6858,7 +6872,7 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
6858
6872
|
* that is not read stays `unknown` — unread, never failed.
|
|
6859
6873
|
*/
|
|
6860
6874
|
async buildSyntheticNodes(topology) {
|
|
6861
|
-
const usage = await this.ctx.api.
|
|
6875
|
+
const usage = await this.ctx.api.recordingArchive.getStorageUsage.query({}).catch((err) => {
|
|
6862
6876
|
this.ctx.logger.warn("ha-export: could not read storage usage, the footage entities go unknown", { meta: { error: errMsg(err) } });
|
|
6863
6877
|
return null;
|
|
6864
6878
|
});
|
|
@@ -7202,7 +7216,7 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
7202
7216
|
});
|
|
7203
7217
|
return null;
|
|
7204
7218
|
});
|
|
7205
|
-
const recordingEnabled = await this.ctx.api.
|
|
7219
|
+
const recordingEnabled = await this.ctx.api.recordingArchive.getDeviceConfig.query({ deviceId }).then((config) => config.enabled).catch((err) => {
|
|
7206
7220
|
this.ctx.logger.warn("ha-export: could not read recording config, the recording function degrades", {
|
|
7207
7221
|
tags: { deviceId },
|
|
7208
7222
|
meta: { error: errMsg(err) }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as buildAddonRouteProvider, F as deviceExportCapability, Nt as EventCategory, Q as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, gt as BaseAddon, i as CAMERA_SWITCH_ORDER, kt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, xt as nodePin } from "../dist-
|
|
1
|
+
import { C as buildAddonRouteProvider, F as deviceExportCapability, Nt as EventCategory, Q as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, gt as BaseAddon, i as CAMERA_SWITCH_ORDER, kt as string, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, xt as nodePin } from "../dist-CzKKAmb9.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
//#region src/ha-export/topics.ts
|
|
4
4
|
/**
|
|
@@ -2867,6 +2867,10 @@ var CAPS_NOT_EXPORTED = [
|
|
|
2867
2867
|
cap: "videoclips",
|
|
2868
2868
|
reason: "Media retrieval by handle, not a state. Clips reach the operator through notifications and the viewer."
|
|
2869
2869
|
},
|
|
2870
|
+
{
|
|
2871
|
+
cap: "recording",
|
|
2872
|
+
reason: "Since D625 this is the per-camera COVERAGE and PLAYBACK collection: which sources a camera has recordings in, what each covers over a window, and how to play an instant of it. Every method takes a window and a chosen source, so nothing here is a state a descriptor could publish — an entity would have to invent both. What an operator actually wants in Home Assistant is \"is this camera recording\", and that is `RecordingConfig.enabled` on `recording-archive`, which the camera-function switches already export as the ONE authority (D62). A second entity over this cap would be the second knob that decision forbids."
|
|
2873
|
+
},
|
|
2870
2874
|
{
|
|
2871
2875
|
cap: "webrtc-session",
|
|
2872
2876
|
reason: "A session opener — the definition of transport."
|
|
@@ -4033,8 +4037,8 @@ async function applyCameraFunctionWrite(api, deviceId, write, sourceNodeId) {
|
|
|
4033
4037
|
});
|
|
4034
4038
|
return;
|
|
4035
4039
|
case "recording-enabled": {
|
|
4036
|
-
const config = await api.
|
|
4037
|
-
await api.
|
|
4040
|
+
const config = await api.recordingArchive.getDeviceConfig.query({ deviceId });
|
|
4041
|
+
await api.recordingArchive.setDeviceConfig.mutate({
|
|
4038
4042
|
deviceId,
|
|
4039
4043
|
config: {
|
|
4040
4044
|
...config,
|
|
@@ -4929,9 +4933,11 @@ function projectMotion(deviceKey, input) {
|
|
|
4929
4933
|
/**
|
|
4930
4934
|
* A clearing edge carries no timestamp. `last_detection` answers "when
|
|
4931
4935
|
* did something last happen", and restamping it when nothing happened
|
|
4932
|
-
* makes an idle camera look permanently busy.
|
|
4936
|
+
* makes an idle camera look permanently busy. Same for a detection whose
|
|
4937
|
+
* timestamp is unknown or implausible — omitted rather than published as
|
|
4938
|
+
* a lie the automation author would trust.
|
|
4933
4939
|
*/
|
|
4934
|
-
if (input.detected) values.push({
|
|
4940
|
+
if (input.detected && input.timestamp !== null) values.push({
|
|
4935
4941
|
topic: stateTopic(deviceKey, "motion_last_detection"),
|
|
4936
4942
|
value: iso(input.timestamp)
|
|
4937
4943
|
});
|
|
@@ -5921,6 +5927,13 @@ var PUSH_PATH = "/api/camstack/push";
|
|
|
5921
5927
|
var MEDIA_ROUTE_PREFIX = `/addon/${ADDON_ID}/ha-media`;
|
|
5922
5928
|
/** How long `doorbell_pressed` stays on before its OFF edge is published. */
|
|
5923
5929
|
var DOORBELL_PULSE_MS = 5e3;
|
|
5930
|
+
/**
|
|
5931
|
+
* The earliest timestamp a real change could plausibly carry. Below this,
|
|
5932
|
+
* a slice field is a placeholder or a seeded "known value, unknown change
|
|
5933
|
+
* time" stamp (e.g. Homematic's `HM_SEEDED_CHANGED_AT = 1`) — never a real
|
|
5934
|
+
* instant. Year 2000 predates every device this addon exports.
|
|
5935
|
+
*/
|
|
5936
|
+
var MIN_PLAUSIBLE_TIMESTAMP_MS = Date.UTC(2e3, 0, 1);
|
|
5924
5937
|
/** The hub's API port — where the data plane is reverse-proxied. */
|
|
5925
5938
|
var HUB_API_PORT = 4443;
|
|
5926
5939
|
/** One PTZ button press, as a relative move. */
|
|
@@ -6223,9 +6236,10 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
6223
6236
|
const detected = slice["detected"];
|
|
6224
6237
|
const lastDetectedAt = readNumber(slice, "lastDetectedAt");
|
|
6225
6238
|
if (typeof detected !== "boolean") return;
|
|
6239
|
+
const timestamp = lastDetectedAt === null ? Date.now() : lastDetectedAt >= MIN_PLAUSIBLE_TIMESTAMP_MS ? lastDetectedAt : null;
|
|
6226
6240
|
this.push(deviceId, projectMotion(deviceKey, {
|
|
6227
6241
|
detected,
|
|
6228
|
-
timestamp
|
|
6242
|
+
timestamp
|
|
6229
6243
|
}));
|
|
6230
6244
|
}
|
|
6231
6245
|
}
|
|
@@ -6853,7 +6867,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
6853
6867
|
* that is not read stays `unknown` — unread, never failed.
|
|
6854
6868
|
*/
|
|
6855
6869
|
async buildSyntheticNodes(topology) {
|
|
6856
|
-
const usage = await this.ctx.api.
|
|
6870
|
+
const usage = await this.ctx.api.recordingArchive.getStorageUsage.query({}).catch((err) => {
|
|
6857
6871
|
this.ctx.logger.warn("ha-export: could not read storage usage, the footage entities go unknown", { meta: { error: errMsg(err) } });
|
|
6858
6872
|
return null;
|
|
6859
6873
|
});
|
|
@@ -7197,7 +7211,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
7197
7211
|
});
|
|
7198
7212
|
return null;
|
|
7199
7213
|
});
|
|
7200
|
-
const recordingEnabled = await this.ctx.api.
|
|
7214
|
+
const recordingEnabled = await this.ctx.api.recordingArchive.getDeviceConfig.query({ deviceId }).then((config) => config.enabled).catch((err) => {
|
|
7201
7215
|
this.ctx.logger.warn("ha-export: could not read recording config, the recording function degrades", {
|
|
7202
7216
|
tags: { deviceId },
|
|
7203
7217
|
meta: { error: errMsg(err) }
|