@camstack/addon-provider-homeassistant 1.2.649 → 1.2.651
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 +13 -0
- package/dist/addon.js +2 -1
- package/dist/addon.mjs +2 -1
- package/dist/{ha-broker-source-D3FBA6uG.mjs → ha-broker-source-CCmZ9I6P.mjs} +142 -31
- package/dist/{ha-broker-source-CE3nHkyW.js → ha-broker-source-D4_TtF2V.js} +142 -31
- package/dist/ha-export/ha-export.addon.js +174 -42
- package/dist/ha-export/ha-export.addon.mjs +174 -42
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.2.651] - 2026-11-02
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- A Home Assistant restart no longer parks the link for 10 minutes: a 404 must persist for a minute before the component counts as missing, and a suspended link is now logged and reported on every reconcile
|
|
15
|
+
|
|
16
|
+
## [1.2.650] - 2026-11-02
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Home Assistant export: a cover offers position and tilt only when the device declares them, shows unavailable while its provider is offline, and a refused command now answers 422 with the reason
|
|
21
|
+
- A cover exports the stop control to Home Assistant only when the device declares cover-stoppable, and a Home Assistant cover with the STOP bit declares it.
|
|
22
|
+
|
|
10
23
|
## [1.2.649] - 2026-11-02
|
|
11
24
|
|
|
12
25
|
### Changed
|
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_ha_broker_source = require("./ha-broker-source-
|
|
2
|
+
const require_ha_broker_source = require("./ha-broker-source-D4_TtF2V.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
|
|
@@ -6328,6 +6328,7 @@ function mapCover(attributes, deviceClass) {
|
|
|
6328
6328
|
const features = [];
|
|
6329
6329
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6330
6330
|
if (sf !== null && (sf & 4) !== 0) features.push(require_ha_broker_source.DeviceFeature.CoverPositionable);
|
|
6331
|
+
if (sf !== null && (sf & 8) !== 0) features.push(require_ha_broker_source.DeviceFeature.CoverStoppable);
|
|
6331
6332
|
if (sf !== null && (sf & 128) !== 0) features.push(require_ha_broker_source.DeviceFeature.CoverTilt);
|
|
6332
6333
|
return {
|
|
6333
6334
|
deviceType: require_ha_broker_source.DeviceType.Cover,
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as humiditySensorCapability, $t as discriminatedUnion, A as brokerCapability, At as tamperCapability, C as alarmPanelCapability, Ct as runningFromMediaPlayer, D as bestLocationMatch, E as batteryCapability, Et as scriptRunnerCapability, F as carbonMonoxideCapability, Ft as vacuumControlCapability, G as deviceAdoptionCapability, Gt as defineEntryKind, H as controlCapability, Ht as baseUnitOf, I as climateControlCapability, It as valveCapability, J as eventEmitterCapability, Kt as defineRecordKinds, L as colorCapability, Lt as vibrationCapability, M as buildDeviceAdminUrl, Mt as tryConvertDelta, N as buttonCapability, Nt as tryConvertUnit, O as binaryCapability, Ot as smokeCapability, P as calendarSourceCapability, Pt as updateCapability, Q as humidifierCapability, Qt as boolean, R as connectivityCapability, Rt as waterHeaterCapability, S as airQualitySensorCapability, St as runningFromLawnMower, T as automationControlCapability, Tt as runningStateCapability, U as coverCapability, Ut as createEvent, V as contactCapability, Vt as RecordSecretUnavailableError, W as deviceAdminLinkCapability, X as floodCapability, Xt as _enum, Y as fanControlCapability, Z as gasCapability, Zt as array, a as BaseDevice, an as union, at as motionCapability, b as accessoriesCapability, bt as resolveAttachmentUrls, cn as DeviceFeature, ct as notifierCapability, dn as errMsg, dt as parseAdminBase, en as literal, et as imageCapability, fn as EventCategory, ft as powerMeterCapability, gt as pressureSensorCapability, ht as presenceCapability, in as string, it as mediaPlayerCapability, j as buildAddonRouteProvider, jt as temperatureSensorCapability, k as brightnessCapability, kt as switchCapability, ln as DeviceRole, lt as numericSensorCapability, mt as prepareNotification, nn as object, nt as lawnMowerControlCapability, o as BaseDeviceProvider, on as unknown, ot as normalizeUnit, p as EnumSensorDateTimeFormatSchema, q as enumSensorCapability, qt as entryBody, rn as record, rt as lockControlCapability, sn as url, st as notificationOutputCapability, t as HA_BROKER_KIND, tn as number, tt as ingestReading, un as DeviceType, v as RUNNING_STATE_COLD, vt as publicEndpointReaderFrom, w as ambientLightSensorCapability, wt as runningFromVacuumState, x as addonRoutesCapability, y as TargetSchema, yt as quantityFromUnit, zt as weatherCapability } from "./ha-broker-source-
|
|
1
|
+
import { $ as humiditySensorCapability, $t as discriminatedUnion, A as brokerCapability, At as tamperCapability, C as alarmPanelCapability, Ct as runningFromMediaPlayer, D as bestLocationMatch, E as batteryCapability, Et as scriptRunnerCapability, F as carbonMonoxideCapability, Ft as vacuumControlCapability, G as deviceAdoptionCapability, Gt as defineEntryKind, H as controlCapability, Ht as baseUnitOf, I as climateControlCapability, It as valveCapability, J as eventEmitterCapability, Kt as defineRecordKinds, L as colorCapability, Lt as vibrationCapability, M as buildDeviceAdminUrl, Mt as tryConvertDelta, N as buttonCapability, Nt as tryConvertUnit, O as binaryCapability, Ot as smokeCapability, P as calendarSourceCapability, Pt as updateCapability, Q as humidifierCapability, Qt as boolean, R as connectivityCapability, Rt as waterHeaterCapability, S as airQualitySensorCapability, St as runningFromLawnMower, T as automationControlCapability, Tt as runningStateCapability, U as coverCapability, Ut as createEvent, V as contactCapability, Vt as RecordSecretUnavailableError, W as deviceAdminLinkCapability, X as floodCapability, Xt as _enum, Y as fanControlCapability, Z as gasCapability, Zt as array, a as BaseDevice, an as union, at as motionCapability, b as accessoriesCapability, bt as resolveAttachmentUrls, cn as DeviceFeature, ct as notifierCapability, dn as errMsg, dt as parseAdminBase, en as literal, et as imageCapability, fn as EventCategory, ft as powerMeterCapability, gt as pressureSensorCapability, ht as presenceCapability, in as string, it as mediaPlayerCapability, j as buildAddonRouteProvider, jt as temperatureSensorCapability, k as brightnessCapability, kt as switchCapability, ln as DeviceRole, lt as numericSensorCapability, mt as prepareNotification, nn as object, nt as lawnMowerControlCapability, o as BaseDeviceProvider, on as unknown, ot as normalizeUnit, p as EnumSensorDateTimeFormatSchema, q as enumSensorCapability, qt as entryBody, rn as record, rt as lockControlCapability, sn as url, st as notificationOutputCapability, t as HA_BROKER_KIND, tn as number, tt as ingestReading, un as DeviceType, v as RUNNING_STATE_COLD, vt as publicEndpointReaderFrom, w as ambientLightSensorCapability, wt as runningFromVacuumState, x as addonRoutesCapability, y as TargetSchema, yt as quantityFromUnit, zt as weatherCapability } from "./ha-broker-source-CCmZ9I6P.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
|
|
@@ -6327,6 +6327,7 @@ function mapCover(attributes, deviceClass) {
|
|
|
6327
6327
|
const features = [];
|
|
6328
6328
|
const sf = readNumericAttr(attributes, "supported_features");
|
|
6329
6329
|
if (sf !== null && (sf & 4) !== 0) features.push(DeviceFeature.CoverPositionable);
|
|
6330
|
+
if (sf !== null && (sf & 8) !== 0) features.push(DeviceFeature.CoverStoppable);
|
|
6330
6331
|
if (sf !== null && (sf & 128) !== 0) features.push(DeviceFeature.CoverTilt);
|
|
6331
6332
|
return {
|
|
6332
6333
|
deviceType: DeviceType.Cover,
|
|
@@ -784,7 +784,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
784
784
|
return EventCategory;
|
|
785
785
|
}({});
|
|
786
786
|
//#endregion
|
|
787
|
-
//#region ../types/dist/device-type-
|
|
787
|
+
//#region ../types/dist/device-type-CfHw_quR.mjs
|
|
788
788
|
/**
|
|
789
789
|
import { errMsg } from '@camstack/types'
|
|
790
790
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -973,6 +973,9 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
973
973
|
DeviceFeature["CoverPositionable"] = "cover-positionable";
|
|
974
974
|
/** Cover exposes slat-tilt control. Gates the tilt slider UI. */
|
|
975
975
|
DeviceFeature["CoverTilt"] = "cover-tilt";
|
|
976
|
+
/** Cover has a real stop: `stop` halts the travel in place. Gates the stop
|
|
977
|
+
* control in exporters; a provider whose `stop` is a no-op never declares it. */
|
|
978
|
+
DeviceFeature["CoverStoppable"] = "cover-stoppable";
|
|
976
979
|
/** Valve exposes intermediate position control (0..100). Gates the
|
|
977
980
|
* position slider / drag surface UI. */
|
|
978
981
|
DeviceFeature["ValvePositionable"] = "valve-positionable";
|
|
@@ -5971,7 +5974,7 @@ var ZodIssueCode = {
|
|
|
5971
5974
|
var ZodFirstPartyTypeKind;
|
|
5972
5975
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5973
5976
|
//#endregion
|
|
5974
|
-
//#region ../types/dist/sleep-
|
|
5977
|
+
//#region ../types/dist/sleep-QsoHs66J.mjs
|
|
5975
5978
|
/**
|
|
5976
5979
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5977
5980
|
* window to float samples (D455).
|
|
@@ -11757,7 +11760,7 @@ object({
|
|
|
11757
11760
|
params: record(string(), union([string(), number()])).optional()
|
|
11758
11761
|
});
|
|
11759
11762
|
//#endregion
|
|
11760
|
-
//#region ../types/dist/composition-
|
|
11763
|
+
//#region ../types/dist/composition-Dh3RfMx5.mjs
|
|
11761
11764
|
/**
|
|
11762
11765
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11763
11766
|
*
|
|
@@ -12971,6 +12974,73 @@ var NodeColorIdSchema = _enum([
|
|
|
12971
12974
|
"node-g",
|
|
12972
12975
|
"node-h"
|
|
12973
12976
|
]);
|
|
12977
|
+
//#endregion
|
|
12978
|
+
//#region ../types/dist/index.mjs
|
|
12979
|
+
var SMTP_INBOUND_DEFAULT_PORT = 2525;
|
|
12980
|
+
var SMTP_INBOUND_DEFAULT_DOMAIN = "camstack.local";
|
|
12981
|
+
var SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES = 25 * 1024 * 1024;
|
|
12982
|
+
/** The text excerpt a message carries on the bus. */
|
|
12983
|
+
var SMTP_INBOUND_TEXT_MAX_CHARS = 4096;
|
|
12984
|
+
var PortSchema = number().int().min(1).max(65535);
|
|
12985
|
+
/** A recipient local-part: what stands before the `@`. */
|
|
12986
|
+
var SmtpRecipientSchema = string().min(1).max(64).regex(/^[A-Za-z0-9._+-]+$/);
|
|
12987
|
+
object({
|
|
12988
|
+
port: PortSchema.default(SMTP_INBOUND_DEFAULT_PORT),
|
|
12989
|
+
bindHost: string().min(1).default("0.0.0.0"),
|
|
12990
|
+
domain: string().min(1).default(SMTP_INBOUND_DEFAULT_DOMAIN),
|
|
12991
|
+
requireAuth: boolean().default(true),
|
|
12992
|
+
username: string().default(""),
|
|
12993
|
+
password: string().default("").meta({ secret: true }),
|
|
12994
|
+
starttls: boolean().default(false),
|
|
12995
|
+
maxMessageBytes: number().int().positive().default(SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES)
|
|
12996
|
+
});
|
|
12997
|
+
object({
|
|
12998
|
+
host: string().min(1).nullable(),
|
|
12999
|
+
hostReason: string().nullable(),
|
|
13000
|
+
port: PortSchema,
|
|
13001
|
+
domain: string().min(1),
|
|
13002
|
+
requireAuth: boolean(),
|
|
13003
|
+
username: string(),
|
|
13004
|
+
password: string(),
|
|
13005
|
+
starttls: boolean()
|
|
13006
|
+
});
|
|
13007
|
+
object({
|
|
13008
|
+
recipients: array(SmtpRecipientSchema).min(1),
|
|
13009
|
+
/**
|
|
13010
|
+
* Who is subscribing. A second `subscribe` with the same id REPLACES that subscriber's
|
|
13011
|
+
* recipients (the way a consumer that restarted, or lost a device, declares its set again);
|
|
13012
|
+
* a recipient held by another subscriber is refused with `smtp-inbound/recipient-claimed`.
|
|
13013
|
+
* Absent, the subscriber is anonymous and unique.
|
|
13014
|
+
*/
|
|
13015
|
+
subscriberId: string().min(1).max(64).optional()
|
|
13016
|
+
});
|
|
13017
|
+
var SmtpInboundAttachmentSchema = object({
|
|
13018
|
+
filename: string(),
|
|
13019
|
+
contentType: string(),
|
|
13020
|
+
bytes: number().int().nonnegative()
|
|
13021
|
+
});
|
|
13022
|
+
/** The payload of one `broker.message` (the key is the recipient local-part). */
|
|
13023
|
+
var SmtpInboundMessageSchema = object({
|
|
13024
|
+
/** Monotonic per mailbox; a gap tells a consumer it missed an event. */
|
|
13025
|
+
seq: number().int().positive(),
|
|
13026
|
+
messageId: string(),
|
|
13027
|
+
receivedAt: number().int().nonnegative(),
|
|
13028
|
+
from: string(),
|
|
13029
|
+
to: string(),
|
|
13030
|
+
subject: string(),
|
|
13031
|
+
text: string().max(SMTP_INBOUND_TEXT_MAX_CHARS),
|
|
13032
|
+
attachments: array(SmtpInboundAttachmentSchema)
|
|
13033
|
+
});
|
|
13034
|
+
object({
|
|
13035
|
+
/** The newest seq issued so far (0 before any mail). */
|
|
13036
|
+
lastSeq: number().int().nonnegative(),
|
|
13037
|
+
/** The oldest seq still retained; messages below it are gone. */
|
|
13038
|
+
oldestSeq: number().int().nonnegative(),
|
|
13039
|
+
messages: array(object({
|
|
13040
|
+
key: string(),
|
|
13041
|
+
message: SmtpInboundMessageSchema
|
|
13042
|
+
}))
|
|
13043
|
+
});
|
|
12974
13044
|
new Set([
|
|
12975
13045
|
"track",
|
|
12976
13046
|
"face",
|
|
@@ -55740,15 +55810,9 @@ var AvailableIntegrationTypeSchema = object({
|
|
|
55740
55810
|
* branch on CAP — never on addon name. `device-adoption` integrations
|
|
55741
55811
|
* (Home Assistant, …) route through the broker step (Approach A);
|
|
55742
55812
|
* `device-provider` integrations (Reolink/ONVIF) keep the
|
|
55743
|
-
* legacy config → discovery flow.
|
|
55744
|
-
* connection as typed records (`integration-instances`, D985): no devices,
|
|
55745
|
-
* no discovery.
|
|
55813
|
+
* legacy config → discovery flow.
|
|
55746
55814
|
*/
|
|
55747
|
-
kind: _enum([
|
|
55748
|
-
"device-adoption",
|
|
55749
|
-
"device-provider",
|
|
55750
|
-
"connection"
|
|
55751
|
-
]),
|
|
55815
|
+
kind: _enum(["device-adoption", "device-provider"]),
|
|
55752
55816
|
/**
|
|
55753
55817
|
* For `device-adoption` addons: the broker kind to create/link
|
|
55754
55818
|
* (e.g. `home-assistant`), declared in the addon manifest. `null` for
|
|
@@ -55862,18 +55926,17 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
55862
55926
|
});
|
|
55863
55927
|
/**
|
|
55864
55928
|
* `integration-instances` - the connection of an addon that holds ONE or SEVERAL
|
|
55865
|
-
* (an account, a relay, a destination) as typed records,
|
|
55866
|
-
*
|
|
55929
|
+
* (an account, a relay, a destination) as typed records (D985, D986). The addon's
|
|
55930
|
+
* own function page reads and writes them (Logging for Loki); the Integrations
|
|
55931
|
+
* page lists only the integrations that bring devices (D996).
|
|
55867
55932
|
*
|
|
55868
|
-
* A collection of providers: each addon that holds connections registers one
|
|
55869
|
-
*
|
|
55870
|
-
* `addonId`. It is internal and has no route: the operator-facing surface is
|
|
55871
|
-
* the `integrations` cap, which keeps ONE list.
|
|
55933
|
+
* A collection of providers: each addon that holds connections registers one and a
|
|
55934
|
+
* caller reaches a provider with the pinned `addonId`.
|
|
55872
55935
|
*
|
|
55873
|
-
* Identity: the instance id
|
|
55874
|
-
*
|
|
55875
|
-
*
|
|
55876
|
-
* editable label.
|
|
55936
|
+
* Identity: the instance id is immutable and opaque to the caller. A record the
|
|
55937
|
+
* Loki migration made keeps the `integrations` registry id it was created under
|
|
55938
|
+
* (`int_NNNN`); a single instance made by its function page takes the addon id.
|
|
55939
|
+
* `name` is the editable label.
|
|
55877
55940
|
*
|
|
55878
55941
|
* Secrets: every field the instance kind marks `.meta({ secret: true })` reaches
|
|
55879
55942
|
* the form as a `SecretFieldView`, never text (D789). A patch value omitted, `''`
|
|
@@ -55904,6 +55967,11 @@ var IntegrationInstanceSchema = object({
|
|
|
55904
55967
|
name: string(),
|
|
55905
55968
|
/** The addon's own rule (an URL is present, a client id is present...). */
|
|
55906
55969
|
configured: boolean(),
|
|
55970
|
+
/**
|
|
55971
|
+
* The instance's own on/off switch (D996): always present, derived from the record body
|
|
55972
|
+
* (`enabled !== false`, so a row written before the field existed is on).
|
|
55973
|
+
*/
|
|
55974
|
+
enabled: boolean(),
|
|
55907
55975
|
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
55908
55976
|
formValues: record(string(), unknown()),
|
|
55909
55977
|
status: IntegrationInstanceStatusSchema.optional()
|
|
@@ -55914,13 +55982,31 @@ var IntegrationInstancePatchSchema = object({
|
|
|
55914
55982
|
/** Omitted / '' / redaction token keeps a secret; `{ $secretClear: true }` clears it. */
|
|
55915
55983
|
values: record(string(), unknown())
|
|
55916
55984
|
});
|
|
55917
|
-
method(_void(), IntegrationInstanceDescriptionSchema), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3), method(_void(), array(IntegrationInstanceSchema).readonly()), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable()), method(object({
|
|
55985
|
+
method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }), method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }), method(object({
|
|
55918
55986
|
id: IntegrationInstanceIdSchema,
|
|
55919
55987
|
name: string().min(1)
|
|
55920
|
-
}), object({ id: string() }), {
|
|
55988
|
+
}), object({ id: string() }), {
|
|
55989
|
+
kind: "mutation",
|
|
55990
|
+
auth: "admin"
|
|
55991
|
+
}), method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
|
|
55992
|
+
kind: "mutation",
|
|
55993
|
+
auth: "admin"
|
|
55994
|
+
}), method(object({
|
|
55995
|
+
id: IntegrationInstanceIdSchema,
|
|
55996
|
+
enabled: boolean()
|
|
55997
|
+
}), object({ ok: literal(true) }), {
|
|
55998
|
+
kind: "mutation",
|
|
55999
|
+
auth: "admin"
|
|
56000
|
+
}), method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
|
|
56001
|
+
kind: "mutation",
|
|
56002
|
+
auth: "admin"
|
|
56003
|
+
}), optionalMethod(object({
|
|
55921
56004
|
id: IntegrationInstanceIdSchema.nullable(),
|
|
55922
56005
|
values: record(string(), unknown())
|
|
55923
|
-
}), TestConnectionResultSchema$1, {
|
|
56006
|
+
}), TestConnectionResultSchema$1, {
|
|
56007
|
+
kind: "mutation",
|
|
56008
|
+
auth: "admin"
|
|
56009
|
+
});
|
|
55924
56010
|
/**
|
|
55925
56011
|
* Two-way audio / talk-back cap. Clients open a WebRTC audio-only
|
|
55926
56012
|
* session (server-initiated offer pattern, identical to the main
|
|
@@ -66689,7 +66775,14 @@ var NcMediaPolicySchema = object({
|
|
|
66689
66775
|
*/
|
|
66690
66776
|
profile: CamProfileSchema.optional(),
|
|
66691
66777
|
/** See {@link NcLinkedCameraModeSchema}. */
|
|
66692
|
-
linkedCameras: NcLinkedCameraModeSchema.optional()
|
|
66778
|
+
linkedCameras: NcLinkedCameraModeSchema.optional(),
|
|
66779
|
+
/**
|
|
66780
|
+
* Sensor rules only: may this rule wake a SLEEPING battery camera to take
|
|
66781
|
+
* the linked still it attaches (D998)? Absent means yes, an explicit `false`
|
|
66782
|
+
* opts out. Deliberately not a Zod default: a rule that never chose keeps
|
|
66783
|
+
* following the hub's. One bounded wake per event; nothing is attached later.
|
|
66784
|
+
*/
|
|
66785
|
+
wakeSleepingCamera: boolean().optional()
|
|
66693
66786
|
});
|
|
66694
66787
|
/**
|
|
66695
66788
|
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
@@ -75270,7 +75363,16 @@ var smokeCapability = {
|
|
|
75270
75363
|
* future fields without breaking the existing call sites.
|
|
75271
75364
|
*/
|
|
75272
75365
|
var EmailAddressSchema = email();
|
|
75366
|
+
/**
|
|
75367
|
+
* Which relay of a multi-relay provider answers (D996). Absent = the provider's first / default
|
|
75368
|
+
* relay, so a caller written before relays existed keeps working unchanged. A provider with one
|
|
75369
|
+
* fixed relay ignores it. This is the integration instance id (`int_NNNN`), NOT the addon id: the
|
|
75370
|
+
* collection pin `addonId` still picks the provider, `instanceId` picks the relay inside it.
|
|
75371
|
+
*/
|
|
75372
|
+
var InstanceIdSchema = string().min(1).optional();
|
|
75373
|
+
var RelayPinSchema = object({ instanceId: InstanceIdSchema });
|
|
75273
75374
|
var SendEmailInputSchema = object({
|
|
75375
|
+
instanceId: InstanceIdSchema,
|
|
75274
75376
|
to: union([EmailAddressSchema, array(EmailAddressSchema).min(1)]),
|
|
75275
75377
|
cc: array(EmailAddressSchema).optional(),
|
|
75276
75378
|
bcc: array(EmailAddressSchema).optional(),
|
|
@@ -75306,11 +75408,11 @@ method(SendEmailInputSchema, SendEmailResultSchema, {
|
|
|
75306
75408
|
kind: "mutation",
|
|
75307
75409
|
auth: "admin",
|
|
75308
75410
|
access: "create"
|
|
75309
|
-
}), method(
|
|
75411
|
+
}), method(RelayPinSchema, SmtpStatusSchema, {
|
|
75310
75412
|
kind: "mutation",
|
|
75311
75413
|
auth: "admin",
|
|
75312
75414
|
access: "view"
|
|
75313
|
-
}), method(
|
|
75415
|
+
}), method(RelayPinSchema, SmtpStatusSchema, { auth: "admin" });
|
|
75314
75416
|
/**
|
|
75315
75417
|
* A single device snapshot returned as base64 JPEG/PNG.
|
|
75316
75418
|
*
|
|
@@ -75342,10 +75444,12 @@ DeviceType.Camera, method(object({
|
|
|
75342
75444
|
* even when the cache is well within the device's
|
|
75343
75445
|
* `snapshotMaxAgeS` window.
|
|
75344
75446
|
*
|
|
75345
|
-
* **`force` is
|
|
75447
|
+
* **`force` is a demand with a named principal, not a freshness
|
|
75448
|
+
* preference** — an operator button, the scheduled refresh (D847), or a
|
|
75449
|
+
* notification rule that left the camera's wake allowed (D998). On a
|
|
75346
75450
|
* battery camera it is the one thing that walks past the wrapper's
|
|
75347
|
-
* sleep gate and wakes the camera, so a
|
|
75348
|
-
*
|
|
75451
|
+
* sleep gate and wakes the camera, so a poller, a thumbnail or a
|
|
75452
|
+
* prestream must NEVER set it. Every such caller
|
|
75349
75453
|
* gets the cached frame, which on a sleeping battery camera is the
|
|
75350
75454
|
* correct answer: stale but honest beats woken.
|
|
75351
75455
|
*/
|
|
@@ -80195,7 +80299,7 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
80195
80299
|
if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
|
|
80196
80300
|
return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
|
|
80197
80301
|
}
|
|
80198
|
-
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
80302
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
80199
80303
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
80200
80304
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
80201
80305
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
@@ -85420,6 +85524,13 @@ Object.freeze({
|
|
|
85420
85524
|
access: "view",
|
|
85421
85525
|
role: "admin"
|
|
85422
85526
|
},
|
|
85527
|
+
"integrationInstances.setInstanceEnabled": {
|
|
85528
|
+
capName: "integration-instances",
|
|
85529
|
+
capScope: "system",
|
|
85530
|
+
addonId: null,
|
|
85531
|
+
access: "create",
|
|
85532
|
+
role: "admin"
|
|
85533
|
+
},
|
|
85423
85534
|
"integrationInstances.testInstance": {
|
|
85424
85535
|
capName: "integration-instances",
|
|
85425
85536
|
capScope: "system",
|
|
@@ -785,7 +785,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
785
785
|
return EventCategory;
|
|
786
786
|
}({});
|
|
787
787
|
//#endregion
|
|
788
|
-
//#region ../types/dist/device-type-
|
|
788
|
+
//#region ../types/dist/device-type-CfHw_quR.mjs
|
|
789
789
|
/**
|
|
790
790
|
import { errMsg } from '@camstack/types'
|
|
791
791
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -974,6 +974,9 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
974
974
|
DeviceFeature["CoverPositionable"] = "cover-positionable";
|
|
975
975
|
/** Cover exposes slat-tilt control. Gates the tilt slider UI. */
|
|
976
976
|
DeviceFeature["CoverTilt"] = "cover-tilt";
|
|
977
|
+
/** Cover has a real stop: `stop` halts the travel in place. Gates the stop
|
|
978
|
+
* control in exporters; a provider whose `stop` is a no-op never declares it. */
|
|
979
|
+
DeviceFeature["CoverStoppable"] = "cover-stoppable";
|
|
977
980
|
/** Valve exposes intermediate position control (0..100). Gates the
|
|
978
981
|
* position slider / drag surface UI. */
|
|
979
982
|
DeviceFeature["ValvePositionable"] = "valve-positionable";
|
|
@@ -5972,7 +5975,7 @@ var ZodIssueCode = {
|
|
|
5972
5975
|
var ZodFirstPartyTypeKind;
|
|
5973
5976
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5974
5977
|
//#endregion
|
|
5975
|
-
//#region ../types/dist/sleep-
|
|
5978
|
+
//#region ../types/dist/sleep-QsoHs66J.mjs
|
|
5976
5979
|
/**
|
|
5977
5980
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5978
5981
|
* window to float samples (D455).
|
|
@@ -11758,7 +11761,7 @@ object({
|
|
|
11758
11761
|
params: record(string(), union([string(), number()])).optional()
|
|
11759
11762
|
});
|
|
11760
11763
|
//#endregion
|
|
11761
|
-
//#region ../types/dist/composition-
|
|
11764
|
+
//#region ../types/dist/composition-Dh3RfMx5.mjs
|
|
11762
11765
|
/**
|
|
11763
11766
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11764
11767
|
*
|
|
@@ -12972,6 +12975,73 @@ var NodeColorIdSchema = _enum([
|
|
|
12972
12975
|
"node-g",
|
|
12973
12976
|
"node-h"
|
|
12974
12977
|
]);
|
|
12978
|
+
//#endregion
|
|
12979
|
+
//#region ../types/dist/index.mjs
|
|
12980
|
+
var SMTP_INBOUND_DEFAULT_PORT = 2525;
|
|
12981
|
+
var SMTP_INBOUND_DEFAULT_DOMAIN = "camstack.local";
|
|
12982
|
+
var SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES = 25 * 1024 * 1024;
|
|
12983
|
+
/** The text excerpt a message carries on the bus. */
|
|
12984
|
+
var SMTP_INBOUND_TEXT_MAX_CHARS = 4096;
|
|
12985
|
+
var PortSchema = number().int().min(1).max(65535);
|
|
12986
|
+
/** A recipient local-part: what stands before the `@`. */
|
|
12987
|
+
var SmtpRecipientSchema = string().min(1).max(64).regex(/^[A-Za-z0-9._+-]+$/);
|
|
12988
|
+
object({
|
|
12989
|
+
port: PortSchema.default(SMTP_INBOUND_DEFAULT_PORT),
|
|
12990
|
+
bindHost: string().min(1).default("0.0.0.0"),
|
|
12991
|
+
domain: string().min(1).default(SMTP_INBOUND_DEFAULT_DOMAIN),
|
|
12992
|
+
requireAuth: boolean().default(true),
|
|
12993
|
+
username: string().default(""),
|
|
12994
|
+
password: string().default("").meta({ secret: true }),
|
|
12995
|
+
starttls: boolean().default(false),
|
|
12996
|
+
maxMessageBytes: number().int().positive().default(SMTP_INBOUND_DEFAULT_MAX_MESSAGE_BYTES)
|
|
12997
|
+
});
|
|
12998
|
+
object({
|
|
12999
|
+
host: string().min(1).nullable(),
|
|
13000
|
+
hostReason: string().nullable(),
|
|
13001
|
+
port: PortSchema,
|
|
13002
|
+
domain: string().min(1),
|
|
13003
|
+
requireAuth: boolean(),
|
|
13004
|
+
username: string(),
|
|
13005
|
+
password: string(),
|
|
13006
|
+
starttls: boolean()
|
|
13007
|
+
});
|
|
13008
|
+
object({
|
|
13009
|
+
recipients: array(SmtpRecipientSchema).min(1),
|
|
13010
|
+
/**
|
|
13011
|
+
* Who is subscribing. A second `subscribe` with the same id REPLACES that subscriber's
|
|
13012
|
+
* recipients (the way a consumer that restarted, or lost a device, declares its set again);
|
|
13013
|
+
* a recipient held by another subscriber is refused with `smtp-inbound/recipient-claimed`.
|
|
13014
|
+
* Absent, the subscriber is anonymous and unique.
|
|
13015
|
+
*/
|
|
13016
|
+
subscriberId: string().min(1).max(64).optional()
|
|
13017
|
+
});
|
|
13018
|
+
var SmtpInboundAttachmentSchema = object({
|
|
13019
|
+
filename: string(),
|
|
13020
|
+
contentType: string(),
|
|
13021
|
+
bytes: number().int().nonnegative()
|
|
13022
|
+
});
|
|
13023
|
+
/** The payload of one `broker.message` (the key is the recipient local-part). */
|
|
13024
|
+
var SmtpInboundMessageSchema = object({
|
|
13025
|
+
/** Monotonic per mailbox; a gap tells a consumer it missed an event. */
|
|
13026
|
+
seq: number().int().positive(),
|
|
13027
|
+
messageId: string(),
|
|
13028
|
+
receivedAt: number().int().nonnegative(),
|
|
13029
|
+
from: string(),
|
|
13030
|
+
to: string(),
|
|
13031
|
+
subject: string(),
|
|
13032
|
+
text: string().max(SMTP_INBOUND_TEXT_MAX_CHARS),
|
|
13033
|
+
attachments: array(SmtpInboundAttachmentSchema)
|
|
13034
|
+
});
|
|
13035
|
+
object({
|
|
13036
|
+
/** The newest seq issued so far (0 before any mail). */
|
|
13037
|
+
lastSeq: number().int().nonnegative(),
|
|
13038
|
+
/** The oldest seq still retained; messages below it are gone. */
|
|
13039
|
+
oldestSeq: number().int().nonnegative(),
|
|
13040
|
+
messages: array(object({
|
|
13041
|
+
key: string(),
|
|
13042
|
+
message: SmtpInboundMessageSchema
|
|
13043
|
+
}))
|
|
13044
|
+
});
|
|
12975
13045
|
new Set([
|
|
12976
13046
|
"track",
|
|
12977
13047
|
"face",
|
|
@@ -55741,15 +55811,9 @@ var AvailableIntegrationTypeSchema = object({
|
|
|
55741
55811
|
* branch on CAP — never on addon name. `device-adoption` integrations
|
|
55742
55812
|
* (Home Assistant, …) route through the broker step (Approach A);
|
|
55743
55813
|
* `device-provider` integrations (Reolink/ONVIF) keep the
|
|
55744
|
-
* legacy config → discovery flow.
|
|
55745
|
-
* connection as typed records (`integration-instances`, D985): no devices,
|
|
55746
|
-
* no discovery.
|
|
55814
|
+
* legacy config → discovery flow.
|
|
55747
55815
|
*/
|
|
55748
|
-
kind: _enum([
|
|
55749
|
-
"device-adoption",
|
|
55750
|
-
"device-provider",
|
|
55751
|
-
"connection"
|
|
55752
|
-
]),
|
|
55816
|
+
kind: _enum(["device-adoption", "device-provider"]),
|
|
55753
55817
|
/**
|
|
55754
55818
|
* For `device-adoption` addons: the broker kind to create/link
|
|
55755
55819
|
* (e.g. `home-assistant`), declared in the addon manifest. `null` for
|
|
@@ -55863,18 +55927,17 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
55863
55927
|
});
|
|
55864
55928
|
/**
|
|
55865
55929
|
* `integration-instances` - the connection of an addon that holds ONE or SEVERAL
|
|
55866
|
-
* (an account, a relay, a destination) as typed records,
|
|
55867
|
-
*
|
|
55930
|
+
* (an account, a relay, a destination) as typed records (D985, D986). The addon's
|
|
55931
|
+
* own function page reads and writes them (Logging for Loki); the Integrations
|
|
55932
|
+
* page lists only the integrations that bring devices (D996).
|
|
55868
55933
|
*
|
|
55869
|
-
* A collection of providers: each addon that holds connections registers one
|
|
55870
|
-
*
|
|
55871
|
-
* `addonId`. It is internal and has no route: the operator-facing surface is
|
|
55872
|
-
* the `integrations` cap, which keeps ONE list.
|
|
55934
|
+
* A collection of providers: each addon that holds connections registers one and a
|
|
55935
|
+
* caller reaches a provider with the pinned `addonId`.
|
|
55873
55936
|
*
|
|
55874
|
-
* Identity: the instance id
|
|
55875
|
-
*
|
|
55876
|
-
*
|
|
55877
|
-
* editable label.
|
|
55937
|
+
* Identity: the instance id is immutable and opaque to the caller. A record the
|
|
55938
|
+
* Loki migration made keeps the `integrations` registry id it was created under
|
|
55939
|
+
* (`int_NNNN`); a single instance made by its function page takes the addon id.
|
|
55940
|
+
* `name` is the editable label.
|
|
55878
55941
|
*
|
|
55879
55942
|
* Secrets: every field the instance kind marks `.meta({ secret: true })` reaches
|
|
55880
55943
|
* the form as a `SecretFieldView`, never text (D789). A patch value omitted, `''`
|
|
@@ -55905,6 +55968,11 @@ var IntegrationInstanceSchema = object({
|
|
|
55905
55968
|
name: string(),
|
|
55906
55969
|
/** The addon's own rule (an URL is present, a client id is present...). */
|
|
55907
55970
|
configured: boolean(),
|
|
55971
|
+
/**
|
|
55972
|
+
* The instance's own on/off switch (D996): always present, derived from the record body
|
|
55973
|
+
* (`enabled !== false`, so a row written before the field existed is on).
|
|
55974
|
+
*/
|
|
55975
|
+
enabled: boolean(),
|
|
55908
55976
|
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
55909
55977
|
formValues: record(string(), unknown()),
|
|
55910
55978
|
status: IntegrationInstanceStatusSchema.optional()
|
|
@@ -55915,13 +55983,31 @@ var IntegrationInstancePatchSchema = object({
|
|
|
55915
55983
|
/** Omitted / '' / redaction token keeps a secret; `{ $secretClear: true }` clears it. */
|
|
55916
55984
|
values: record(string(), unknown())
|
|
55917
55985
|
});
|
|
55918
|
-
method(_void(), IntegrationInstanceDescriptionSchema), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3), method(_void(), array(IntegrationInstanceSchema).readonly()), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable()), method(object({
|
|
55986
|
+
method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }), method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }), method(object({
|
|
55919
55987
|
id: IntegrationInstanceIdSchema,
|
|
55920
55988
|
name: string().min(1)
|
|
55921
|
-
}), object({ id: string() }), {
|
|
55989
|
+
}), object({ id: string() }), {
|
|
55990
|
+
kind: "mutation",
|
|
55991
|
+
auth: "admin"
|
|
55992
|
+
}), method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
|
|
55993
|
+
kind: "mutation",
|
|
55994
|
+
auth: "admin"
|
|
55995
|
+
}), method(object({
|
|
55996
|
+
id: IntegrationInstanceIdSchema,
|
|
55997
|
+
enabled: boolean()
|
|
55998
|
+
}), object({ ok: literal(true) }), {
|
|
55999
|
+
kind: "mutation",
|
|
56000
|
+
auth: "admin"
|
|
56001
|
+
}), method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
|
|
56002
|
+
kind: "mutation",
|
|
56003
|
+
auth: "admin"
|
|
56004
|
+
}), optionalMethod(object({
|
|
55922
56005
|
id: IntegrationInstanceIdSchema.nullable(),
|
|
55923
56006
|
values: record(string(), unknown())
|
|
55924
|
-
}), TestConnectionResultSchema$1, {
|
|
56007
|
+
}), TestConnectionResultSchema$1, {
|
|
56008
|
+
kind: "mutation",
|
|
56009
|
+
auth: "admin"
|
|
56010
|
+
});
|
|
55925
56011
|
/**
|
|
55926
56012
|
* Two-way audio / talk-back cap. Clients open a WebRTC audio-only
|
|
55927
56013
|
* session (server-initiated offer pattern, identical to the main
|
|
@@ -66690,7 +66776,14 @@ var NcMediaPolicySchema = object({
|
|
|
66690
66776
|
*/
|
|
66691
66777
|
profile: CamProfileSchema.optional(),
|
|
66692
66778
|
/** See {@link NcLinkedCameraModeSchema}. */
|
|
66693
|
-
linkedCameras: NcLinkedCameraModeSchema.optional()
|
|
66779
|
+
linkedCameras: NcLinkedCameraModeSchema.optional(),
|
|
66780
|
+
/**
|
|
66781
|
+
* Sensor rules only: may this rule wake a SLEEPING battery camera to take
|
|
66782
|
+
* the linked still it attaches (D998)? Absent means yes, an explicit `false`
|
|
66783
|
+
* opts out. Deliberately not a Zod default: a rule that never chose keeps
|
|
66784
|
+
* following the hub's. One bounded wake per event; nothing is attached later.
|
|
66785
|
+
*/
|
|
66786
|
+
wakeSleepingCamera: boolean().optional()
|
|
66694
66787
|
});
|
|
66695
66788
|
/**
|
|
66696
66789
|
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
@@ -75271,7 +75364,16 @@ var smokeCapability = {
|
|
|
75271
75364
|
* future fields without breaking the existing call sites.
|
|
75272
75365
|
*/
|
|
75273
75366
|
var EmailAddressSchema = email();
|
|
75367
|
+
/**
|
|
75368
|
+
* Which relay of a multi-relay provider answers (D996). Absent = the provider's first / default
|
|
75369
|
+
* relay, so a caller written before relays existed keeps working unchanged. A provider with one
|
|
75370
|
+
* fixed relay ignores it. This is the integration instance id (`int_NNNN`), NOT the addon id: the
|
|
75371
|
+
* collection pin `addonId` still picks the provider, `instanceId` picks the relay inside it.
|
|
75372
|
+
*/
|
|
75373
|
+
var InstanceIdSchema = string().min(1).optional();
|
|
75374
|
+
var RelayPinSchema = object({ instanceId: InstanceIdSchema });
|
|
75274
75375
|
var SendEmailInputSchema = object({
|
|
75376
|
+
instanceId: InstanceIdSchema,
|
|
75275
75377
|
to: union([EmailAddressSchema, array(EmailAddressSchema).min(1)]),
|
|
75276
75378
|
cc: array(EmailAddressSchema).optional(),
|
|
75277
75379
|
bcc: array(EmailAddressSchema).optional(),
|
|
@@ -75307,11 +75409,11 @@ method(SendEmailInputSchema, SendEmailResultSchema, {
|
|
|
75307
75409
|
kind: "mutation",
|
|
75308
75410
|
auth: "admin",
|
|
75309
75411
|
access: "create"
|
|
75310
|
-
}), method(
|
|
75412
|
+
}), method(RelayPinSchema, SmtpStatusSchema, {
|
|
75311
75413
|
kind: "mutation",
|
|
75312
75414
|
auth: "admin",
|
|
75313
75415
|
access: "view"
|
|
75314
|
-
}), method(
|
|
75416
|
+
}), method(RelayPinSchema, SmtpStatusSchema, { auth: "admin" });
|
|
75315
75417
|
/**
|
|
75316
75418
|
* A single device snapshot returned as base64 JPEG/PNG.
|
|
75317
75419
|
*
|
|
@@ -75343,10 +75445,12 @@ DeviceType.Camera, method(object({
|
|
|
75343
75445
|
* even when the cache is well within the device's
|
|
75344
75446
|
* `snapshotMaxAgeS` window.
|
|
75345
75447
|
*
|
|
75346
|
-
* **`force` is
|
|
75448
|
+
* **`force` is a demand with a named principal, not a freshness
|
|
75449
|
+
* preference** — an operator button, the scheduled refresh (D847), or a
|
|
75450
|
+
* notification rule that left the camera's wake allowed (D998). On a
|
|
75347
75451
|
* battery camera it is the one thing that walks past the wrapper's
|
|
75348
|
-
* sleep gate and wakes the camera, so a
|
|
75349
|
-
*
|
|
75452
|
+
* sleep gate and wakes the camera, so a poller, a thumbnail or a
|
|
75453
|
+
* prestream must NEVER set it. Every such caller
|
|
75350
75454
|
* gets the cached frame, which on a sleeping battery camera is the
|
|
75351
75455
|
* correct answer: stale but honest beats woken.
|
|
75352
75456
|
*/
|
|
@@ -80196,7 +80300,7 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
80196
80300
|
if (state === "paused") return nativeSlice(false, "paused", previous, transitionAtMs, fetchedAt, null);
|
|
80197
80301
|
return nativeSlice(false, state, previous, transitionAtMs, fetchedAt, null);
|
|
80198
80302
|
}
|
|
80199
|
-
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
80303
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
80200
80304
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
80201
80305
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
80202
80306
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
@@ -85421,6 +85525,13 @@ Object.freeze({
|
|
|
85421
85525
|
access: "view",
|
|
85422
85526
|
role: "admin"
|
|
85423
85527
|
},
|
|
85528
|
+
"integrationInstances.setInstanceEnabled": {
|
|
85529
|
+
capName: "integration-instances",
|
|
85530
|
+
capScope: "system",
|
|
85531
|
+
addonId: null,
|
|
85532
|
+
access: "create",
|
|
85533
|
+
role: "admin"
|
|
85534
|
+
},
|
|
85424
85535
|
"integrationInstances.testInstance": {
|
|
85425
85536
|
capName: "integration-instances",
|
|
85426
85537
|
capScope: "system",
|