@camstack/addon-provider-homeassistant 1.2.657 → 1.2.658
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/CHANGELOG.md +7 -0
- package/dist/addon.js +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/ha-export/ha-export.addon.js +35 -14
- package/dist/ha-export/ha-export.addon.mjs +35 -14
- package/dist/{ha-instance-settings-DJXP_6Rg.js → ha-instance-settings-CRvQ5rH6.js} +15 -1
- package/dist/{ha-instance-settings-CxalgfRa.mjs → ha-instance-settings-qhCNJbbn.mjs} +15 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.2.658] - 2026-11-04
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Fixed the Home Assistant export migration reading every switch as off after the instances moved to typed records; it now reads the legacy integration row and refuses when that row is unreadable.
|
|
15
|
+
- Image links sent to Home Assistant now prefer the public endpoint (falling back to the internal address when none is set), so notifications show images away from home.
|
|
16
|
+
|
|
10
17
|
## [1.2.657] - 2026-11-04
|
|
11
18
|
|
|
12
19
|
### Changed
|
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_ha_instance_settings = require("./ha-instance-settings-
|
|
2
|
+
const require_ha_instance_settings = require("./ha-instance-settings-CRvQ5rH6.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_zlib = require("node:zlib");
|
|
5
5
|
//#region src/ha-admin-link.ts
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as fanControlCapability, $t as createEvent, A as bestLocationMatch, At as runningFromMediaPlayer, B as climateControlCapability, Bt as tryConvertDelta, C as accessoriesCapability, Ct as pressureSensorCapability, D as ambientLightSensorCapability, Dt as resolveAttachmentUrls, E as alarmPanelCapability, Et as quantityFromUnit, F as buildAddonRouteProvider, Ft as smokeCapability, G as contactCapability, Gt as vibrationCapability, H as connectivityCapability, Ht as updateCapability, I as buildDeviceAdminUrl, J as deviceAdminLinkCapability, K as controlCapability, Kt as waterHeaterCapability, L as buttonCapability, Lt as switchCapability, M as boardKeySourceCapability, Mt as runningStateCapability, N as brightnessCapability, Nt as scriptRunnerCapability, O as automationControlCapability, P as brokerCapability, Q as eventEmitterCapability, Qt as baseUnitOf, R as calendarSourceCapability, Rt as tamperCapability, S as TargetSchema, Sn as EventCategory, St as presenceCapability, T as airQualitySensorCapability, Tt as publicEndpointReaderFrom, Ut as vacuumControlCapability, V as colorCapability, Vt as tryConvertUnit, Wt as valveCapability, Xt as RecordSecretUnavailableError, Y as deviceAdoptionCapability, Z as enumSensorCapability, _n as url, at as humiditySensorCapability, b as RUNNING_STATE_COLD, bn as DeviceType, bt as preconditionOf, cn as boolean, ct as integrationInstancesCapability, dn as number, dt as mediaPlayerCapability, en as defineAddonMigrations, et as flattenNestedRecords, fn as object, ft as motionCapability, gn as unknown, gt as numericSensorCapability, hn as union, ht as notifierCapability, it as humidifierCapability, j as binaryCapability, jt as runningFromVacuumState, k as batteryCapability, kt as runningFromLawnMower, ln as discriminatedUnion, lt as lawnMowerControlCapability, m as EnumSensorDateTimeFormatSchema, mn as string, mt as notificationOutputCapability, n as HA_BROKER_KIND, nn as defineRecordKinds, nt as floodCapability, o as BaseDevice, on as _enum, ot as imageCapability, pn as record, pt as normalizeUnit, q as coverCapability, qt as weatherCapability, rn as entryBody, rt as gasCapability, s as BaseDeviceProvider, sn as array, st as ingestReading, t as haInstanceSettingsPortsOver, tn as defineEntryKind, tt as flattenPortsOver, un as literal, ut as lockControlCapability, vn as DeviceFeature, vt as parseAdminBase, w as addonRoutesCapability, x as RecordIntegrationInstances, xn as errMsg, xt as prepareNotification, yn as DeviceRole, yt as powerMeterCapability, z as carbonMonoxideCapability, zt as temperatureSensorCapability } from "./ha-instance-settings-
|
|
1
|
+
import { $ as fanControlCapability, $t as createEvent, A as bestLocationMatch, At as runningFromMediaPlayer, B as climateControlCapability, Bt as tryConvertDelta, C as accessoriesCapability, Ct as pressureSensorCapability, D as ambientLightSensorCapability, Dt as resolveAttachmentUrls, E as alarmPanelCapability, Et as quantityFromUnit, F as buildAddonRouteProvider, Ft as smokeCapability, G as contactCapability, Gt as vibrationCapability, H as connectivityCapability, Ht as updateCapability, I as buildDeviceAdminUrl, J as deviceAdminLinkCapability, K as controlCapability, Kt as waterHeaterCapability, L as buttonCapability, Lt as switchCapability, M as boardKeySourceCapability, Mt as runningStateCapability, N as brightnessCapability, Nt as scriptRunnerCapability, O as automationControlCapability, P as brokerCapability, Q as eventEmitterCapability, Qt as baseUnitOf, R as calendarSourceCapability, Rt as tamperCapability, S as TargetSchema, Sn as EventCategory, St as presenceCapability, T as airQualitySensorCapability, Tt as publicEndpointReaderFrom, Ut as vacuumControlCapability, V as colorCapability, Vt as tryConvertUnit, Wt as valveCapability, Xt as RecordSecretUnavailableError, Y as deviceAdoptionCapability, Z as enumSensorCapability, _n as url, at as humiditySensorCapability, b as RUNNING_STATE_COLD, bn as DeviceType, bt as preconditionOf, cn as boolean, ct as integrationInstancesCapability, dn as number, dt as mediaPlayerCapability, en as defineAddonMigrations, et as flattenNestedRecords, fn as object, ft as motionCapability, gn as unknown, gt as numericSensorCapability, hn as union, ht as notifierCapability, it as humidifierCapability, j as binaryCapability, jt as runningFromVacuumState, k as batteryCapability, kt as runningFromLawnMower, ln as discriminatedUnion, lt as lawnMowerControlCapability, m as EnumSensorDateTimeFormatSchema, mn as string, mt as notificationOutputCapability, n as HA_BROKER_KIND, nn as defineRecordKinds, nt as floodCapability, o as BaseDevice, on as _enum, ot as imageCapability, pn as record, pt as normalizeUnit, q as coverCapability, qt as weatherCapability, rn as entryBody, rt as gasCapability, s as BaseDeviceProvider, sn as array, st as ingestReading, t as haInstanceSettingsPortsOver, tn as defineEntryKind, tt as flattenPortsOver, un as literal, ut as lockControlCapability, vn as DeviceFeature, vt as parseAdminBase, w as addonRoutesCapability, x as RecordIntegrationInstances, xn as errMsg, xt as prepareNotification, yn as DeviceRole, yt as powerMeterCapability, z as carbonMonoxideCapability, zt as temperatureSensorCapability } from "./ha-instance-settings-qhCNJbbn.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
4
4
|
//#region src/ha-admin-link.ts
|
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
//#endregion
|
|
27
|
-
const require_ha_instance_settings = require("../ha-instance-settings-
|
|
27
|
+
const require_ha_instance_settings = require("../ha-instance-settings-CRvQ5rH6.js");
|
|
28
28
|
let node_crypto = require("node:crypto");
|
|
29
29
|
require("node:zlib");
|
|
30
30
|
let node_fs = require("node:fs");
|
|
@@ -5090,13 +5090,21 @@ function verifyExpiringUrl(input) {
|
|
|
5090
5090
|
/** The hub address roles a Home Assistant media link may be minted on. */
|
|
5091
5091
|
var HA_MEDIA_ROLES = ["internal", "publicEndpoint"];
|
|
5092
5092
|
/**
|
|
5093
|
-
* The base a media link is minted on: the hub's role (D734)
|
|
5094
|
-
*
|
|
5095
|
-
* when
|
|
5096
|
-
*
|
|
5093
|
+
* The base a media link is minted on: the hub's role (D734) the broker chose. Links reach
|
|
5094
|
+
* Home Assistant notifications on phones away from home, so a new broker chooses `publicEndpoint`;
|
|
5095
|
+
* when that resolves to nothing the `internal` address answers instead (a LAN Home Assistant still
|
|
5096
|
+
* gets an image). A broker that chose `internal` never falls back to public. Ranked by
|
|
5097
|
+
* `local-network`, never loopback (`null` when nothing resolves): a link Home Assistant cannot
|
|
5098
|
+
* open is worse than no image.
|
|
5097
5099
|
*/
|
|
5098
|
-
function haMediaBaseUrl(book, role = "
|
|
5099
|
-
|
|
5100
|
+
function haMediaBaseUrl(book, role = "publicEndpoint") {
|
|
5101
|
+
const chosen = book.roles[role].resolved;
|
|
5102
|
+
if (chosen !== null || role !== "publicEndpoint") return chosen;
|
|
5103
|
+
return book.roles.internal.resolved;
|
|
5104
|
+
}
|
|
5105
|
+
/** True when `haMediaBaseUrl` answered with the internal address because the public endpoint was chosen but unset. */
|
|
5106
|
+
function usedInternalFallback(book, role) {
|
|
5107
|
+
return role === "publicEndpoint" && book.roles.publicEndpoint.resolved === null && book.roles.internal.resolved !== null;
|
|
5100
5108
|
}
|
|
5101
5109
|
/** brokerId → media base, each broker on ITS role. Pure: the caller reads the palette per use. */
|
|
5102
5110
|
function mediaBasesByBroker(brokerIds, book, roleOf) {
|
|
@@ -5279,6 +5287,8 @@ function integrationByBroker(rows, warn) {
|
|
|
5279
5287
|
/** Every broker the old shape has something for, with the value the old reader would have used. */
|
|
5280
5288
|
function legacyLinks(stored, rows, warn) {
|
|
5281
5289
|
const membership = membershipOf$1(stored[MEMBERSHIP_KEY]);
|
|
5290
|
+
const unreadable = rows.find((row) => Object.keys(row.settings).length === 0);
|
|
5291
|
+
if (unreadable !== void 0 && membership.size > 0) throw new Error(`the settings of integration ${unreadable.integrationId} read as empty; the export switch cannot be carried from an unreadable source, nothing was written`);
|
|
5282
5292
|
const integrations = integrationByBroker(rows, warn);
|
|
5283
5293
|
const brokers = new Set(membership.keys());
|
|
5284
5294
|
for (const key of Object.keys(stored)) for (const prefix of [EXPORT_PREFIX, ROLE_PREFIX]) if (key.startsWith(prefix) && key.length > prefix.length) brokers.add(key.slice(prefix.length));
|
|
@@ -5472,12 +5482,12 @@ var haExportLinksKind = require_ha_instance_settings.defineEntryKind(HA_EXPORT_L
|
|
|
5472
5482
|
schema: HaExportLinksBodySchema,
|
|
5473
5483
|
writeTrigger: "an operator switches the export of a Home Assistant instance, picks its image-link address, or exports a device to it"
|
|
5474
5484
|
});
|
|
5475
|
-
/** A link the operator has not touched: off, on the
|
|
5485
|
+
/** A link the operator has not touched: off, on the public endpoint, no device. */
|
|
5476
5486
|
function defaultLinks(name) {
|
|
5477
5487
|
return {
|
|
5478
5488
|
name,
|
|
5479
5489
|
exportTo: false,
|
|
5480
|
-
mediaRole: "
|
|
5490
|
+
mediaRole: "publicEndpoint",
|
|
5481
5491
|
devices: []
|
|
5482
5492
|
};
|
|
5483
5493
|
}
|
|
@@ -5521,7 +5531,7 @@ var ExportLinks = class ExportLinks {
|
|
|
5521
5531
|
return this.rows.get(brokerId)?.exportTo === true;
|
|
5522
5532
|
}
|
|
5523
5533
|
mediaRole(brokerId) {
|
|
5524
|
-
return this.rows.get(brokerId)?.mediaRole ?? "
|
|
5534
|
+
return this.rows.get(brokerId)?.mediaRole ?? "publicEndpoint";
|
|
5525
5535
|
}
|
|
5526
5536
|
/** brokerId → exported device ids, for the brokers that export at least one. */
|
|
5527
5537
|
membership() {
|
|
@@ -8247,6 +8257,7 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
|
|
|
8247
8257
|
}
|
|
8248
8258
|
/** deviceId:cap:field already reported. Bounded by devices × mapped caps. */
|
|
8249
8259
|
warnedCapFields = /* @__PURE__ */ new Set();
|
|
8260
|
+
warnedMediaFallback = /* @__PURE__ */ new Set();
|
|
8250
8261
|
warnOnce(deviceId, capName, field, line) {
|
|
8251
8262
|
const key = `${deviceId}:${capName}:${field}`;
|
|
8252
8263
|
if (this.warnedCapFields.has(key)) return;
|
|
@@ -10023,14 +10034,24 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
|
|
|
10023
10034
|
}
|
|
10024
10035
|
/**
|
|
10025
10036
|
* Each broker's media base, read per use: the palette's role the broker chose
|
|
10026
|
-
* (the `ha-export-links` record's `mediaRole`, `
|
|
10037
|
+
* (the `ha-export-links` record's `mediaRole`, `publicEndpoint` by default, internal when none is set). A role that resolves to nothing
|
|
10027
10038
|
* is `null` and says so — the image entities then carry no value, which reads as
|
|
10028
10039
|
* empty rather than as a broken link.
|
|
10029
10040
|
*/
|
|
10030
10041
|
async mediaBasesFor(brokerIds, deviceId) {
|
|
10031
10042
|
let bases;
|
|
10032
10043
|
try {
|
|
10033
|
-
|
|
10044
|
+
const answer = await this.ctx.api.localNetwork.getAddresses.query();
|
|
10045
|
+
bases = mediaBasesByBroker(brokerIds, answer, (brokerId) => this.book().mediaRole(brokerId));
|
|
10046
|
+
for (const brokerId of brokerIds) {
|
|
10047
|
+
if (this.warnedMediaFallback.has(brokerId)) continue;
|
|
10048
|
+
if (!usedInternalFallback(answer, this.book().mediaRole(brokerId))) continue;
|
|
10049
|
+
this.warnedMediaFallback.add(brokerId);
|
|
10050
|
+
this.ctx.logger.info("ha-export: no public endpoint is set, so image links use the internal address", {
|
|
10051
|
+
tags: { deviceId },
|
|
10052
|
+
meta: { brokerId }
|
|
10053
|
+
});
|
|
10054
|
+
}
|
|
10034
10055
|
} catch (err) {
|
|
10035
10056
|
this.ctx.logger.debug("ha-export: could not resolve the media base URLs", {
|
|
10036
10057
|
tags: { deviceId },
|
|
@@ -10127,7 +10148,7 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
|
|
|
10127
10148
|
id: "ha-export-transport",
|
|
10128
10149
|
title: "Connection",
|
|
10129
10150
|
titleKey: "provider-homeassistant:globalSettings.s_ha-export-transport.title",
|
|
10130
|
-
description: "The hub address each Home Assistant instance fetches image links from.
|
|
10151
|
+
description: "The hub address each Home Assistant instance fetches image links from. Public endpoint is the default, so notifications show images away from home; when none is set the internal address is used. Choose Internal to never use the public endpoint.",
|
|
10131
10152
|
columns: 1,
|
|
10132
10153
|
fields: this.config.knownBrokers.map((broker) => ({
|
|
10133
10154
|
type: "select",
|
|
@@ -10140,7 +10161,7 @@ var HaExportAddon = class extends require_ha_instance_settings.BaseAddon {
|
|
|
10140
10161
|
value: "publicEndpoint",
|
|
10141
10162
|
label: "Public endpoint (reachable from outside)"
|
|
10142
10163
|
}],
|
|
10143
|
-
default: "
|
|
10164
|
+
default: "publicEndpoint"
|
|
10144
10165
|
}))
|
|
10145
10166
|
}] : [],
|
|
10146
10167
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as buildAddonRouteProvider, It as statusInstanceOf, Jt as BaseAddon, Ot as runExportedAction, Pt as sendToExportedTarget, Qt as baseUnitOf, Sn as EventCategory, U as consumableFormOf, W as consumableKindOf, X as deviceExportCapability, Zt as RevConflictError, _ as HvacModeSchema, _t as oauthIntegrationCapability, a as AlarmArmModeSchema, an as nodePin, bt as preconditionOf, c as CAMERA_SWITCH_ORDER, cn as boolean, d as ConsumableFormSchema, en as defineAddonMigrations, f as ConsumableItemSchema, fn as object, g as FanDirectionSchema, gn as unknown, h as ExportInstanceUnknownError, i as listHomeAssistantBrokers, in as isReadingQuantity, l as COCO_TO_MACRO, mn as string, on as _enum, p as ConsumableStatusSchema, sn as array, t as haInstanceSettingsPortsOver, tn as defineEntryKind, u as CameraSwitchIdSchema, v as MediaPlayerRepeatSchema, w as addonRoutesCapability, wt as pruneDeletedEntities, y as PLUG_APPLIANCE_TYPES } from "../ha-instance-settings-
|
|
1
|
+
import { F as buildAddonRouteProvider, It as statusInstanceOf, Jt as BaseAddon, Ot as runExportedAction, Pt as sendToExportedTarget, Qt as baseUnitOf, Sn as EventCategory, U as consumableFormOf, W as consumableKindOf, X as deviceExportCapability, Zt as RevConflictError, _ as HvacModeSchema, _t as oauthIntegrationCapability, a as AlarmArmModeSchema, an as nodePin, bt as preconditionOf, c as CAMERA_SWITCH_ORDER, cn as boolean, d as ConsumableFormSchema, en as defineAddonMigrations, f as ConsumableItemSchema, fn as object, g as FanDirectionSchema, gn as unknown, h as ExportInstanceUnknownError, i as listHomeAssistantBrokers, in as isReadingQuantity, l as COCO_TO_MACRO, mn as string, on as _enum, p as ConsumableStatusSchema, sn as array, t as haInstanceSettingsPortsOver, tn as defineEntryKind, u as CameraSwitchIdSchema, v as MediaPlayerRepeatSchema, w as addonRoutesCapability, wt as pruneDeletedEntities, y as PLUG_APPLIANCE_TYPES } from "../ha-instance-settings-qhCNJbbn.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
import "node:zlib";
|
|
4
4
|
import "node:fs";
|
|
@@ -5055,13 +5055,21 @@ function verifyExpiringUrl(input) {
|
|
|
5055
5055
|
/** The hub address roles a Home Assistant media link may be minted on. */
|
|
5056
5056
|
var HA_MEDIA_ROLES = ["internal", "publicEndpoint"];
|
|
5057
5057
|
/**
|
|
5058
|
-
* The base a media link is minted on: the hub's role (D734)
|
|
5059
|
-
*
|
|
5060
|
-
* when
|
|
5061
|
-
*
|
|
5058
|
+
* The base a media link is minted on: the hub's role (D734) the broker chose. Links reach
|
|
5059
|
+
* Home Assistant notifications on phones away from home, so a new broker chooses `publicEndpoint`;
|
|
5060
|
+
* when that resolves to nothing the `internal` address answers instead (a LAN Home Assistant still
|
|
5061
|
+
* gets an image). A broker that chose `internal` never falls back to public. Ranked by
|
|
5062
|
+
* `local-network`, never loopback (`null` when nothing resolves): a link Home Assistant cannot
|
|
5063
|
+
* open is worse than no image.
|
|
5062
5064
|
*/
|
|
5063
|
-
function haMediaBaseUrl(book, role = "
|
|
5064
|
-
|
|
5065
|
+
function haMediaBaseUrl(book, role = "publicEndpoint") {
|
|
5066
|
+
const chosen = book.roles[role].resolved;
|
|
5067
|
+
if (chosen !== null || role !== "publicEndpoint") return chosen;
|
|
5068
|
+
return book.roles.internal.resolved;
|
|
5069
|
+
}
|
|
5070
|
+
/** True when `haMediaBaseUrl` answered with the internal address because the public endpoint was chosen but unset. */
|
|
5071
|
+
function usedInternalFallback(book, role) {
|
|
5072
|
+
return role === "publicEndpoint" && book.roles.publicEndpoint.resolved === null && book.roles.internal.resolved !== null;
|
|
5065
5073
|
}
|
|
5066
5074
|
/** brokerId → media base, each broker on ITS role. Pure: the caller reads the palette per use. */
|
|
5067
5075
|
function mediaBasesByBroker(brokerIds, book, roleOf) {
|
|
@@ -5244,6 +5252,8 @@ function integrationByBroker(rows, warn) {
|
|
|
5244
5252
|
/** Every broker the old shape has something for, with the value the old reader would have used. */
|
|
5245
5253
|
function legacyLinks(stored, rows, warn) {
|
|
5246
5254
|
const membership = membershipOf$1(stored[MEMBERSHIP_KEY]);
|
|
5255
|
+
const unreadable = rows.find((row) => Object.keys(row.settings).length === 0);
|
|
5256
|
+
if (unreadable !== void 0 && membership.size > 0) throw new Error(`the settings of integration ${unreadable.integrationId} read as empty; the export switch cannot be carried from an unreadable source, nothing was written`);
|
|
5247
5257
|
const integrations = integrationByBroker(rows, warn);
|
|
5248
5258
|
const brokers = new Set(membership.keys());
|
|
5249
5259
|
for (const key of Object.keys(stored)) for (const prefix of [EXPORT_PREFIX, ROLE_PREFIX]) if (key.startsWith(prefix) && key.length > prefix.length) brokers.add(key.slice(prefix.length));
|
|
@@ -5423,12 +5433,12 @@ var haExportLinksKind = defineEntryKind("ha-export-links", {
|
|
|
5423
5433
|
}),
|
|
5424
5434
|
writeTrigger: "an operator switches the export of a Home Assistant instance, picks its image-link address, or exports a device to it"
|
|
5425
5435
|
});
|
|
5426
|
-
/** A link the operator has not touched: off, on the
|
|
5436
|
+
/** A link the operator has not touched: off, on the public endpoint, no device. */
|
|
5427
5437
|
function defaultLinks(name) {
|
|
5428
5438
|
return {
|
|
5429
5439
|
name,
|
|
5430
5440
|
exportTo: false,
|
|
5431
|
-
mediaRole: "
|
|
5441
|
+
mediaRole: "publicEndpoint",
|
|
5432
5442
|
devices: []
|
|
5433
5443
|
};
|
|
5434
5444
|
}
|
|
@@ -5472,7 +5482,7 @@ var ExportLinks = class ExportLinks {
|
|
|
5472
5482
|
return this.rows.get(brokerId)?.exportTo === true;
|
|
5473
5483
|
}
|
|
5474
5484
|
mediaRole(brokerId) {
|
|
5475
|
-
return this.rows.get(brokerId)?.mediaRole ?? "
|
|
5485
|
+
return this.rows.get(brokerId)?.mediaRole ?? "publicEndpoint";
|
|
5476
5486
|
}
|
|
5477
5487
|
/** brokerId → exported device ids, for the brokers that export at least one. */
|
|
5478
5488
|
membership() {
|
|
@@ -8198,6 +8208,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
8198
8208
|
}
|
|
8199
8209
|
/** deviceId:cap:field already reported. Bounded by devices × mapped caps. */
|
|
8200
8210
|
warnedCapFields = /* @__PURE__ */ new Set();
|
|
8211
|
+
warnedMediaFallback = /* @__PURE__ */ new Set();
|
|
8201
8212
|
warnOnce(deviceId, capName, field, line) {
|
|
8202
8213
|
const key = `${deviceId}:${capName}:${field}`;
|
|
8203
8214
|
if (this.warnedCapFields.has(key)) return;
|
|
@@ -9974,14 +9985,24 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
9974
9985
|
}
|
|
9975
9986
|
/**
|
|
9976
9987
|
* Each broker's media base, read per use: the palette's role the broker chose
|
|
9977
|
-
* (the `ha-export-links` record's `mediaRole`, `
|
|
9988
|
+
* (the `ha-export-links` record's `mediaRole`, `publicEndpoint` by default, internal when none is set). A role that resolves to nothing
|
|
9978
9989
|
* is `null` and says so — the image entities then carry no value, which reads as
|
|
9979
9990
|
* empty rather than as a broken link.
|
|
9980
9991
|
*/
|
|
9981
9992
|
async mediaBasesFor(brokerIds, deviceId) {
|
|
9982
9993
|
let bases;
|
|
9983
9994
|
try {
|
|
9984
|
-
|
|
9995
|
+
const answer = await this.ctx.api.localNetwork.getAddresses.query();
|
|
9996
|
+
bases = mediaBasesByBroker(brokerIds, answer, (brokerId) => this.book().mediaRole(brokerId));
|
|
9997
|
+
for (const brokerId of brokerIds) {
|
|
9998
|
+
if (this.warnedMediaFallback.has(brokerId)) continue;
|
|
9999
|
+
if (!usedInternalFallback(answer, this.book().mediaRole(brokerId))) continue;
|
|
10000
|
+
this.warnedMediaFallback.add(brokerId);
|
|
10001
|
+
this.ctx.logger.info("ha-export: no public endpoint is set, so image links use the internal address", {
|
|
10002
|
+
tags: { deviceId },
|
|
10003
|
+
meta: { brokerId }
|
|
10004
|
+
});
|
|
10005
|
+
}
|
|
9985
10006
|
} catch (err) {
|
|
9986
10007
|
this.ctx.logger.debug("ha-export: could not resolve the media base URLs", {
|
|
9987
10008
|
tags: { deviceId },
|
|
@@ -10078,7 +10099,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
10078
10099
|
id: "ha-export-transport",
|
|
10079
10100
|
title: "Connection",
|
|
10080
10101
|
titleKey: "provider-homeassistant:globalSettings.s_ha-export-transport.title",
|
|
10081
|
-
description: "The hub address each Home Assistant instance fetches image links from.
|
|
10102
|
+
description: "The hub address each Home Assistant instance fetches image links from. Public endpoint is the default, so notifications show images away from home; when none is set the internal address is used. Choose Internal to never use the public endpoint.",
|
|
10082
10103
|
columns: 1,
|
|
10083
10104
|
fields: this.config.knownBrokers.map((broker) => ({
|
|
10084
10105
|
type: "select",
|
|
@@ -10091,7 +10112,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
10091
10112
|
value: "publicEndpoint",
|
|
10092
10113
|
label: "Public endpoint (reachable from outside)"
|
|
10093
10114
|
}],
|
|
10094
|
-
default: "
|
|
10115
|
+
default: "publicEndpoint"
|
|
10095
10116
|
}))
|
|
10096
10117
|
}] : [],
|
|
10097
10118
|
{
|
|
@@ -5981,7 +5981,7 @@ var ZodIssueCode = {
|
|
|
5981
5981
|
var ZodFirstPartyTypeKind;
|
|
5982
5982
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5983
5983
|
//#endregion
|
|
5984
|
-
//#region ../types/dist/sleep-
|
|
5984
|
+
//#region ../types/dist/sleep-D1jjWAr8.mjs
|
|
5985
5985
|
/**
|
|
5986
5986
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5987
5987
|
* window to float samples (D455).
|
|
@@ -9265,6 +9265,7 @@ function defineEntryKind(name, spec) {
|
|
|
9265
9265
|
class: "config",
|
|
9266
9266
|
writeTrigger: spec.writeTrigger ?? "an operator adds or edits an entry in the entries UI",
|
|
9267
9267
|
retention: { none: "an entry goes only when the operator deletes it" },
|
|
9268
|
+
...spec.maxDataBytes === void 0 ? {} : { maxDataBytes: spec.maxDataBytes },
|
|
9268
9269
|
...spec.database === void 0 ? {} : { database: spec.database },
|
|
9269
9270
|
...spec.indexes === void 0 ? {} : { indexes: spec.indexes },
|
|
9270
9271
|
...spec.secretArrayKeys === void 0 ? {} : { secretArrayKeys: spec.secretArrayKeys },
|
|
@@ -56815,6 +56816,12 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56815
56816
|
}), object({ success: boolean() }), {
|
|
56816
56817
|
kind: "mutation",
|
|
56817
56818
|
auth: "admin"
|
|
56819
|
+
}), method(object({ id: string() }), object({
|
|
56820
|
+
rows: number().int().nonnegative(),
|
|
56821
|
+
secrets: number().int().nonnegative()
|
|
56822
|
+
}), {
|
|
56823
|
+
kind: "mutation",
|
|
56824
|
+
auth: "admin"
|
|
56818
56825
|
}), method(_void(), array(AvailableIntegrationTypeSchema), { auth: "admin" }), method(object({
|
|
56819
56826
|
addonId: string(),
|
|
56820
56827
|
settings: record(string(), unknown())
|
|
@@ -86603,6 +86610,13 @@ Object.freeze({
|
|
|
86603
86610
|
access: "create",
|
|
86604
86611
|
role: "admin"
|
|
86605
86612
|
},
|
|
86613
|
+
"integrations.clearSettings": {
|
|
86614
|
+
capName: "integrations",
|
|
86615
|
+
capScope: "system",
|
|
86616
|
+
addonId: null,
|
|
86617
|
+
access: "delete",
|
|
86618
|
+
role: "admin"
|
|
86619
|
+
},
|
|
86606
86620
|
"integrations.create": {
|
|
86607
86621
|
capName: "integrations",
|
|
86608
86622
|
capScope: "system",
|
|
@@ -5980,7 +5980,7 @@ var ZodIssueCode = {
|
|
|
5980
5980
|
var ZodFirstPartyTypeKind;
|
|
5981
5981
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5982
5982
|
//#endregion
|
|
5983
|
-
//#region ../types/dist/sleep-
|
|
5983
|
+
//#region ../types/dist/sleep-D1jjWAr8.mjs
|
|
5984
5984
|
/**
|
|
5985
5985
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5986
5986
|
* window to float samples (D455).
|
|
@@ -9264,6 +9264,7 @@ function defineEntryKind(name, spec) {
|
|
|
9264
9264
|
class: "config",
|
|
9265
9265
|
writeTrigger: spec.writeTrigger ?? "an operator adds or edits an entry in the entries UI",
|
|
9266
9266
|
retention: { none: "an entry goes only when the operator deletes it" },
|
|
9267
|
+
...spec.maxDataBytes === void 0 ? {} : { maxDataBytes: spec.maxDataBytes },
|
|
9267
9268
|
...spec.database === void 0 ? {} : { database: spec.database },
|
|
9268
9269
|
...spec.indexes === void 0 ? {} : { indexes: spec.indexes },
|
|
9269
9270
|
...spec.secretArrayKeys === void 0 ? {} : { secretArrayKeys: spec.secretArrayKeys },
|
|
@@ -56814,6 +56815,12 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56814
56815
|
}), object({ success: boolean() }), {
|
|
56815
56816
|
kind: "mutation",
|
|
56816
56817
|
auth: "admin"
|
|
56818
|
+
}), method(object({ id: string() }), object({
|
|
56819
|
+
rows: number().int().nonnegative(),
|
|
56820
|
+
secrets: number().int().nonnegative()
|
|
56821
|
+
}), {
|
|
56822
|
+
kind: "mutation",
|
|
56823
|
+
auth: "admin"
|
|
56817
56824
|
}), method(_void(), array(AvailableIntegrationTypeSchema), { auth: "admin" }), method(object({
|
|
56818
56825
|
addonId: string(),
|
|
56819
56826
|
settings: record(string(), unknown())
|
|
@@ -86602,6 +86609,13 @@ Object.freeze({
|
|
|
86602
86609
|
access: "create",
|
|
86603
86610
|
role: "admin"
|
|
86604
86611
|
},
|
|
86612
|
+
"integrations.clearSettings": {
|
|
86613
|
+
capName: "integrations",
|
|
86614
|
+
capScope: "system",
|
|
86615
|
+
addonId: null,
|
|
86616
|
+
access: "delete",
|
|
86617
|
+
role: "admin"
|
|
86618
|
+
},
|
|
86605
86619
|
"integrations.create": {
|
|
86606
86620
|
capName: "integrations",
|
|
86607
86621
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-homeassistant",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.658",
|
|
4
4
|
"description": "Home Assistant device provider addon for CamStack",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"description": "Device provider (import) + native entity export (push). Two addons, one bundle, separate processes."
|
|
135
135
|
},
|
|
136
136
|
"requires": {
|
|
137
|
-
"server": ">=1.2.
|
|
137
|
+
"server": ">=1.2.766"
|
|
138
138
|
}
|
|
139
139
|
},
|
|
140
140
|
"files": [
|