@camstack/addon-provider-homeassistant 1.2.140 → 1.2.142
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 +110 -1
- package/dist/addon.mjs +110 -1
- package/dist/{dist-D1vVHAPR.js → dist-1gj-XZ-R.js} +3353 -21
- package/dist/{dist-DEPiNusb.mjs → dist-DbcraPOl.mjs} +3336 -22
- package/dist/ha-export/ha-export.addon.js +9 -1
- package/dist/ha-export/ha-export.addon.mjs +9 -1
- package/package.json +1 -1
|
@@ -5359,7 +5359,7 @@ var ZodIssueCode = {
|
|
|
5359
5359
|
var ZodFirstPartyTypeKind;
|
|
5360
5360
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5361
5361
|
//#endregion
|
|
5362
|
-
//#region ../types/dist/sleep-
|
|
5362
|
+
//#region ../types/dist/sleep-i3eUVc-d.mjs
|
|
5363
5363
|
/**
|
|
5364
5364
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5365
5365
|
* window to float samples (D455).
|
|
@@ -6989,6 +6989,18 @@ function systemMethod(input, output, options) {
|
|
|
6989
6989
|
systemOnly: true
|
|
6990
6990
|
};
|
|
6991
6991
|
}
|
|
6992
|
+
/**
|
|
6993
|
+
* A method a SOURCE of a collection cap may legitimately not serve — OPTIONAL
|
|
6994
|
+
* on `InferProvider`. The `providerOptional: true` literal is what
|
|
6995
|
+
* `InferProvider` keys on; see {@link CapabilityMethodSchema.providerOptional}
|
|
6996
|
+
* for when this is the honest answer and when it is a soft stub.
|
|
6997
|
+
*/
|
|
6998
|
+
function optionalMethod(input, output, options) {
|
|
6999
|
+
return {
|
|
7000
|
+
...method(input, output, options),
|
|
7001
|
+
providerOptional: true
|
|
7002
|
+
};
|
|
7003
|
+
}
|
|
6992
7004
|
/** Shorthand to define an event schema */
|
|
6993
7005
|
function event(data) {
|
|
6994
7006
|
return { data };
|
|
@@ -7419,6 +7431,8 @@ var EVENT_OWNER_TYPES = [
|
|
|
7419
7431
|
* nothing failing until a caller asked.
|
|
7420
7432
|
*/
|
|
7421
7433
|
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7434
|
+
/** The same list as a Zod enum, for the cap input that carries it. */
|
|
7435
|
+
var MediaPresenceOwnerKindSchema = _enum([...EVENT_OWNER_TYPES, "track"]);
|
|
7422
7436
|
new Set(EVENT_OWNER_TYPES);
|
|
7423
7437
|
/**
|
|
7424
7438
|
* Build an `IAddonRouteProvider` from a list of routes. Implements
|
|
@@ -7971,10 +7985,20 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
|
|
|
7971
7985
|
var CameraSwitchUnavailableReasonSchema = _enum([
|
|
7972
7986
|
"no-provider",
|
|
7973
7987
|
"source-unreachable",
|
|
7974
|
-
"not-configured",
|
|
7975
7988
|
"device-disabled"
|
|
7976
7989
|
]);
|
|
7977
7990
|
/**
|
|
7991
|
+
* Something true about a switch that is nonetheless OFFERED.
|
|
7992
|
+
*
|
|
7993
|
+
* The distinction from {@link CameraSwitchUnavailableReasonSchema} is the
|
|
7994
|
+
* whole point: a reason replaces the control, a warning travels WITH it. The
|
|
7995
|
+
* privacy mask taught us the difference — greying the one button that starts
|
|
7996
|
+
* the feature teaches the operator the feature is broken, while a live toggle
|
|
7997
|
+
* that flips nothing teaches them the switch is broken. Neither is true; the
|
|
7998
|
+
* honest surface is a working toggle that says what is missing.
|
|
7999
|
+
*/
|
|
8000
|
+
var CameraSwitchWarningSchema = _enum(["no-privacy-zones"]);
|
|
8001
|
+
/**
|
|
7978
8002
|
* One switch, resolved for one camera.
|
|
7979
8003
|
*
|
|
7980
8004
|
* `label` and `costWhenOff` travel ON THE WIRE rather than being looked up
|
|
@@ -7993,6 +8017,11 @@ var CameraSwitchSchema = object({
|
|
|
7993
8017
|
/** False = do not render a control. `unavailableReason` says why. */
|
|
7994
8018
|
available: boolean(),
|
|
7995
8019
|
unavailableReason: CameraSwitchUnavailableReasonSchema.optional(),
|
|
8020
|
+
/**
|
|
8021
|
+
* Present on an AVAILABLE switch only. Rendered beside the live control;
|
|
8022
|
+
* never a substitute for one.
|
|
8023
|
+
*/
|
|
8024
|
+
warning: CameraSwitchWarningSchema.optional(),
|
|
7996
8025
|
/** Current state. Meaningless when `available` is false — read it as `true`. */
|
|
7997
8026
|
enabled: boolean(),
|
|
7998
8027
|
authority: CameraSwitchAuthoritySchema
|
|
@@ -8410,11 +8439,31 @@ var RecordingBandTriggersSchema = RecordingTriggersSchema;
|
|
|
8410
8439
|
* band engine's `applies` rule). `start`/`end` are `HH:MM`; an `end <= start`
|
|
8411
8440
|
* span wraps past midnight (handled by the band engine).
|
|
8412
8441
|
*/
|
|
8442
|
+
/**
|
|
8443
|
+
* Whether a band's footage carries sound.
|
|
8444
|
+
*
|
|
8445
|
+
* The recorder has always attached with `audio: 'aac'`, so every band of every
|
|
8446
|
+
* camera recorded sound whether anyone wanted it or not. The broker already
|
|
8447
|
+
* serves the other answer — `audio: 'none'` takes the video-only `/muted`
|
|
8448
|
+
* restream — so this was a choice the product could always have offered.
|
|
8449
|
+
*
|
|
8450
|
+
* It belongs on the BAND rather than the camera because one camera can want
|
|
8451
|
+
* both: silent across the shop floor during opening hours, sound overnight.
|
|
8452
|
+
* And it applies to BOTH modes — an events band firing on motion has the same
|
|
8453
|
+
* question to answer as a continuous one.
|
|
8454
|
+
*/
|
|
8455
|
+
var RecordingBandAudioSchema = _enum(["on", "muted"]);
|
|
8413
8456
|
var RecordingBandSchema = object({
|
|
8414
8457
|
days: array(RecordingWeekdaySchema),
|
|
8415
8458
|
start: string().regex(HHMM),
|
|
8416
8459
|
end: string().regex(HHMM),
|
|
8417
8460
|
mode: RecordingBandModeSchema,
|
|
8461
|
+
/**
|
|
8462
|
+
* Sound, or silence. OPTIONAL and absent-means-`on`: every recording
|
|
8463
|
+
* written before this existed carried sound, and a band whose key is
|
|
8464
|
+
* missing must keep meaning what it meant. See {@link RecordingBandAudioSchema}.
|
|
8465
|
+
*/
|
|
8466
|
+
audio: RecordingBandAudioSchema.optional(),
|
|
8418
8467
|
triggers: RecordingBandTriggersSchema.optional(),
|
|
8419
8468
|
/**
|
|
8420
8469
|
* RETIRED (D381). A band no longer carries a pre-buffer of its own.
|
|
@@ -13828,6 +13877,244 @@ var deviceAdoptionCapability = {
|
|
|
13828
13877
|
}
|
|
13829
13878
|
};
|
|
13830
13879
|
/**
|
|
13880
|
+
* device-admin-link — "this device has a management page of its own, and here
|
|
13881
|
+
* is its address".
|
|
13882
|
+
*
|
|
13883
|
+
* ## Why this is not a `deviceConfig` cap
|
|
13884
|
+
*
|
|
13885
|
+
* There is nothing to edit. A `deviceConfig` cap (D14) exists so the framework
|
|
13886
|
+
* can DERIVE a settings form from `getOptions` + `getStatus` and route a flat
|
|
13887
|
+
* patch back through a setter; it costs a `builderId` reducer in
|
|
13888
|
+
* `device-config-contribution.ts` and a `*-config-schema.ts` beside it, and it
|
|
13889
|
+
* renders a form section. This cap answers ONE question with ONE read and
|
|
13890
|
+
* renders a button. Nothing about it is a form, so it carries no `deviceConfig`
|
|
13891
|
+
* block, no `settings`, no `runtimeState` and no reducer — exactly like
|
|
13892
|
+
* `reboot`, the other pure-RPC device-native cap.
|
|
13893
|
+
*
|
|
13894
|
+
* ## Absent, and the difference between "no page" and "we cannot say"
|
|
13895
|
+
*
|
|
13896
|
+
* The two are answered at DIFFERENT layers, on purpose:
|
|
13897
|
+
*
|
|
13898
|
+
* - **"We cannot say"** → the provider never registers the cap for that
|
|
13899
|
+
* device. A VeSync humidifier, a Petkit feeder, a Dreame vacuum and a Dreo
|
|
13900
|
+
* fan are reached only through a vendor cloud; there is no address to hand
|
|
13901
|
+
* out and no page to open. A Tuya plug, a Wyze camera and a Gree air
|
|
13902
|
+
* conditioner DO have a LAN IP, and still have no HTTP management page
|
|
13903
|
+
* behind it. None of them register, so `deviceManager.getBindings` never
|
|
13904
|
+
* lists the cap and no surface asks.
|
|
13905
|
+
* - **"This device has no page, and I know that"** → the provider registers
|
|
13906
|
+
* and `getAdminLink` returns `null`. This is the answer for a device whose
|
|
13907
|
+
* sibling DOES have a page: a Reolink battery camera reached over UDP by
|
|
13908
|
+
* `uid` with a blank `host`, an Ecowitt gateway configured in `listener`
|
|
13909
|
+
* transport, a Home Assistant broker authenticated by supervisor token
|
|
13910
|
+
* (which carries no `baseUrl` at all).
|
|
13911
|
+
*
|
|
13912
|
+
* Both draw NOTHING. A button that opens a browser error is worse than no
|
|
13913
|
+
* button, and D62 is the same rule from the other side: an off switch is
|
|
13914
|
+
* reported off, never made to look broken. There is no third state where the
|
|
13915
|
+
* UI renders a disabled button "because the device might have a page".
|
|
13916
|
+
*
|
|
13917
|
+
* ## The URL never carries credentials
|
|
13918
|
+
*
|
|
13919
|
+
* Not in userinfo, not in a query string. Every provider builds through
|
|
13920
|
+
* `buildDeviceAdminUrl` (`device-admin-link-url.ts`), which takes host, port,
|
|
13921
|
+
* scheme and path as separate arguments — there is no parameter a secret could
|
|
13922
|
+
* arrive in — and re-checks its own output for the `scheme://user:pass@` shape
|
|
13923
|
+
* that `scripts/check-no-credential-urls-in-fixtures.ts` bans from recorded
|
|
13924
|
+
* output. `scripts/check-admin-link-builder-is-the-only-url-source.ts` is what
|
|
13925
|
+
* keeps providers from hand-rolling one anyway.
|
|
13926
|
+
*
|
|
13927
|
+
* This matters here more than anywhere else in the repo, because every provider
|
|
13928
|
+
* that knows a device's host knows its PASSWORD too: `{ host, port, username,
|
|
13929
|
+
* password }` sit in one object on Hikvision, Amcrest, Reolink and ONVIF alike,
|
|
13930
|
+
* and `http://admin:hunter2@192.168.50.139/` is a URL a browser accepts. The
|
|
13931
|
+
* camera's own page will ask for its own login. That is correct, and pre-
|
|
13932
|
+
* filling it is the operator's business, not ours.
|
|
13933
|
+
*
|
|
13934
|
+
* ## It is a LAN fact
|
|
13935
|
+
*
|
|
13936
|
+
* The URL addresses the device where the NODE can see it. It is not proxied,
|
|
13937
|
+
* not made reachable from outside, and not sent anywhere. A surface renders it
|
|
13938
|
+
* as a link the operator's own browser follows, on the operator's own network,
|
|
13939
|
+
* or renders nothing.
|
|
13940
|
+
*/
|
|
13941
|
+
/**
|
|
13942
|
+
* Whose page is it. The distinction is for the OPERATOR, who needs to know
|
|
13943
|
+
* before clicking whether he is about to land on a camera's own web server or
|
|
13944
|
+
* inside Home Assistant.
|
|
13945
|
+
*/
|
|
13946
|
+
var AdminLinkTargetEnum = _enum(["device", "integration"]);
|
|
13947
|
+
var DeviceAdminLinkSchema = object({
|
|
13948
|
+
/**
|
|
13949
|
+
* Absolute `http(s)://` URL. Built by `buildDeviceAdminUrl` and therefore
|
|
13950
|
+
* free of userinfo and of any credential-shaped query key.
|
|
13951
|
+
*/
|
|
13952
|
+
url: string(),
|
|
13953
|
+
/**
|
|
13954
|
+
* What the surface calls it — "Web UI", "Home Assistant", "UniFi controller".
|
|
13955
|
+
* The PROVIDER names it, because only the provider knows what the page is;
|
|
13956
|
+
* a UI that invented the label from the addon id would call the Home
|
|
13957
|
+
* Assistant device page "Provider Homeassistant".
|
|
13958
|
+
*/
|
|
13959
|
+
label: string(),
|
|
13960
|
+
target: AdminLinkTargetEnum,
|
|
13961
|
+
/**
|
|
13962
|
+
* Host the URL points at, without scheme, port or path — for the tooltip, so
|
|
13963
|
+
* an operator can see WHERE the button goes before he follows it. Redundant
|
|
13964
|
+
* with `url` by construction; carried separately so no surface has to parse
|
|
13965
|
+
* a URL to show it.
|
|
13966
|
+
*/
|
|
13967
|
+
host: string()
|
|
13968
|
+
});
|
|
13969
|
+
var deviceAdminLinkCapability = {
|
|
13970
|
+
name: "device-admin-link",
|
|
13971
|
+
scope: "device",
|
|
13972
|
+
deviceNative: true,
|
|
13973
|
+
mode: "singleton",
|
|
13974
|
+
methods: {
|
|
13975
|
+
/**
|
|
13976
|
+
* The device's management page, or `null` when this device has none.
|
|
13977
|
+
*
|
|
13978
|
+
* `auth: 'admin'` deliberately. This is administration, not actuation —
|
|
13979
|
+
* the same bucket as `reboot` and `camera-credentials`, and explicitly NOT
|
|
13980
|
+
* the actuation set `scripts/check-actuation-not-admin.ts` protects (D403).
|
|
13981
|
+
* The URL is also a statement about the LAN, which a household member with
|
|
13982
|
+
* a `view` grant on a light has no reason to be handed.
|
|
13983
|
+
*
|
|
13984
|
+
* The surfaces gate on the QUERY, never on a role they guessed: a caller
|
|
13985
|
+
* without the right loses the query and draws nothing, which is the same
|
|
13986
|
+
* thing a device with no page draws. There is no path on which a button
|
|
13987
|
+
* appears and then fails — the D403 failure mode, from the other end.
|
|
13988
|
+
*/
|
|
13989
|
+
getAdminLink: method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema.nullable(), { auth: "admin" }) }
|
|
13990
|
+
};
|
|
13991
|
+
/**
|
|
13992
|
+
* Query keys that may never appear on an admin link. A credential smuggled as
|
|
13993
|
+
* `?password=` is the same leak as userinfo, in a form the userinfo check
|
|
13994
|
+
* cannot see: it survives copy-paste, referrer headers and proxy logs
|
|
13995
|
+
* identically.
|
|
13996
|
+
*/
|
|
13997
|
+
var CREDENTIAL_QUERY_KEYS = [
|
|
13998
|
+
"password",
|
|
13999
|
+
"passwd",
|
|
14000
|
+
"pwd",
|
|
14001
|
+
"pass",
|
|
14002
|
+
"user",
|
|
14003
|
+
"username",
|
|
14004
|
+
"usr",
|
|
14005
|
+
"login",
|
|
14006
|
+
"token",
|
|
14007
|
+
"access_token",
|
|
14008
|
+
"auth",
|
|
14009
|
+
"authorization",
|
|
14010
|
+
"apikey",
|
|
14011
|
+
"api_key",
|
|
14012
|
+
"secret",
|
|
14013
|
+
"credential",
|
|
14014
|
+
"credentials",
|
|
14015
|
+
"session",
|
|
14016
|
+
"sessionid",
|
|
14017
|
+
"key"
|
|
14018
|
+
];
|
|
14019
|
+
/**
|
|
14020
|
+
* The same userinfo shape `scripts/check-no-credential-urls-in-fixtures.ts`
|
|
14021
|
+
* scans recorded fixtures for, applied to what we are about to EMIT. Kept
|
|
14022
|
+
* structurally identical on purpose: a URL this function returns is a URL that
|
|
14023
|
+
* guard would pass.
|
|
14024
|
+
*/
|
|
14025
|
+
var CREDENTIAL_URL = /[a-z][a-z0-9+.-]*:\/\/[^/\s:@'"]+:[^/\s:@'"]+@/i;
|
|
14026
|
+
/** A host that is safe to place in an authority component verbatim. */
|
|
14027
|
+
var PLAIN_HOST = /^[a-zA-Z0-9._-]+$/;
|
|
14028
|
+
/** A bracketed IPv6 literal, the only other authority form we emit. */
|
|
14029
|
+
var IPV6_HOST = /^\[[0-9a-fA-F:.]+\]$/;
|
|
14030
|
+
function defaultPortFor(scheme) {
|
|
14031
|
+
return scheme === "https" ? 443 : 80;
|
|
14032
|
+
}
|
|
14033
|
+
/**
|
|
14034
|
+
* Build the admin-page URL, or refuse by name.
|
|
14035
|
+
*
|
|
14036
|
+
* The refusal is never thrown: a provider answering "no page for this device"
|
|
14037
|
+
* is an ordinary answer (`getAdminLink` → `null`), and a throw here would turn
|
|
14038
|
+
* a missing host on one device into a failed query for the whole surface.
|
|
14039
|
+
*/
|
|
14040
|
+
function buildDeviceAdminUrl(parts) {
|
|
14041
|
+
const host = parts.host.trim();
|
|
14042
|
+
if (host.length === 0) return {
|
|
14043
|
+
ok: false,
|
|
14044
|
+
reason: "empty-host"
|
|
14045
|
+
};
|
|
14046
|
+
if (host.includes("@")) return {
|
|
14047
|
+
ok: false,
|
|
14048
|
+
reason: "host-carries-userinfo"
|
|
14049
|
+
};
|
|
14050
|
+
if (!PLAIN_HOST.test(host) && !IPV6_HOST.test(host)) return {
|
|
14051
|
+
ok: false,
|
|
14052
|
+
reason: "host-not-plain"
|
|
14053
|
+
};
|
|
14054
|
+
if (parts.port !== null) {
|
|
14055
|
+
if (!Number.isInteger(parts.port) || parts.port < 1 || parts.port > 65535) return {
|
|
14056
|
+
ok: false,
|
|
14057
|
+
reason: "port-out-of-range"
|
|
14058
|
+
};
|
|
14059
|
+
}
|
|
14060
|
+
if (!parts.path.startsWith("/")) return {
|
|
14061
|
+
ok: false,
|
|
14062
|
+
reason: "path-not-absolute"
|
|
14063
|
+
};
|
|
14064
|
+
const query = parts.query ?? {};
|
|
14065
|
+
for (const key of Object.keys(query)) if (CREDENTIAL_QUERY_KEYS.includes(key.toLowerCase())) return {
|
|
14066
|
+
ok: false,
|
|
14067
|
+
reason: "credential-query-key"
|
|
14068
|
+
};
|
|
14069
|
+
const authority = parts.port === null || parts.port === defaultPortFor(parts.scheme) ? host : `${host}:${String(parts.port)}`;
|
|
14070
|
+
const search = new URLSearchParams();
|
|
14071
|
+
for (const [key, value] of Object.entries(query)) search.append(key, value);
|
|
14072
|
+
const suffix = search.size > 0 ? `?${search.toString()}` : "";
|
|
14073
|
+
const url = `${parts.scheme}://${authority}${parts.path}${suffix}`;
|
|
14074
|
+
if (CREDENTIAL_URL.test(url)) return {
|
|
14075
|
+
ok: false,
|
|
14076
|
+
reason: "userinfo-in-result"
|
|
14077
|
+
};
|
|
14078
|
+
return {
|
|
14079
|
+
ok: true,
|
|
14080
|
+
url
|
|
14081
|
+
};
|
|
14082
|
+
}
|
|
14083
|
+
function parseAdminBase(baseUrl) {
|
|
14084
|
+
const raw = baseUrl.trim();
|
|
14085
|
+
if (raw.length === 0) return {
|
|
14086
|
+
ok: false,
|
|
14087
|
+
reason: "empty"
|
|
14088
|
+
};
|
|
14089
|
+
let parsed;
|
|
14090
|
+
try {
|
|
14091
|
+
parsed = new URL(raw);
|
|
14092
|
+
} catch {
|
|
14093
|
+
return {
|
|
14094
|
+
ok: false,
|
|
14095
|
+
reason: "unparseable"
|
|
14096
|
+
};
|
|
14097
|
+
}
|
|
14098
|
+
if (parsed.username !== "" || parsed.password !== "") return {
|
|
14099
|
+
ok: false,
|
|
14100
|
+
reason: "base-carries-userinfo"
|
|
14101
|
+
};
|
|
14102
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return {
|
|
14103
|
+
ok: false,
|
|
14104
|
+
reason: "scheme-not-http"
|
|
14105
|
+
};
|
|
14106
|
+
const scheme = parsed.protocol === "https:" ? "https" : "http";
|
|
14107
|
+
const port = parsed.port === "" ? null : Number(parsed.port);
|
|
14108
|
+
const basePath = parsed.pathname === "/" ? "" : parsed.pathname.replace(/\/+$/, "");
|
|
14109
|
+
return {
|
|
14110
|
+
ok: true,
|
|
14111
|
+
host: parsed.hostname,
|
|
14112
|
+
port,
|
|
14113
|
+
scheme,
|
|
14114
|
+
basePath
|
|
14115
|
+
};
|
|
14116
|
+
}
|
|
14117
|
+
/**
|
|
13831
14118
|
* `device-export` — collection cap for addons that export camstack
|
|
13832
14119
|
* devices to external ecosystems (HomeAssistant via MQTT discovery,
|
|
13833
14120
|
* HomeKit/HAP, Alexa Smart Home, …).
|
|
@@ -21729,7 +22016,11 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21729
22016
|
ownerType: EventOwnerTypeSchema,
|
|
21730
22017
|
eventId: number().int(),
|
|
21731
22018
|
deviceId: number()
|
|
21732
|
-
}), array(MediaFileInfoSchema).readonly()), method(
|
|
22019
|
+
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
22020
|
+
deviceId: number(),
|
|
22021
|
+
ownerKind: MediaPresenceOwnerKindSchema,
|
|
22022
|
+
ownerIds: array(string()).max(5e3)
|
|
22023
|
+
}), array(string()).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21733
22024
|
kind: "mutation",
|
|
21734
22025
|
auth: "admin"
|
|
21735
22026
|
}), method(RebuildObjectEmbeddingsInput, RebuildObjectEmbeddingsResultSchema, {
|
|
@@ -23396,10 +23687,9 @@ var ServerBootModeSchema = _enum([
|
|
|
23396
23687
|
* - `idle` / `checking` / `staging` — steady / in-flight registry work.
|
|
23397
23688
|
* - `pending-restart` — a version is staged and the node has NOT yet
|
|
23398
23689
|
* restarted onto it (still running the OLD version).
|
|
23399
|
-
* - `awaiting-confirmation` —
|
|
23400
|
-
*
|
|
23401
|
-
*
|
|
23402
|
-
* manually restarted, or the probation boot auto-rolls-back.
|
|
23690
|
+
* - `awaiting-confirmation` — RETIRED with the probation boot (single-copy
|
|
23691
|
+
* collapse, 2026-07-18). Kept in the enum so an older client still parses;
|
|
23692
|
+
* no provider emits it.
|
|
23403
23693
|
*/
|
|
23404
23694
|
var ServerUpdateStateSchema = _enum([
|
|
23405
23695
|
"idle",
|
|
@@ -23488,12 +23778,35 @@ var ServerRollbackInfoSchema = object({
|
|
|
23488
23778
|
var ServerPackageStatusSchema = object({
|
|
23489
23779
|
/** Root package name (`@camstack/server` on the hub). */
|
|
23490
23780
|
packageName: string(),
|
|
23491
|
-
/**
|
|
23781
|
+
/**
|
|
23782
|
+
* Version of the code THIS PROCESS loaded — captured once, at boot, from the
|
|
23783
|
+
* package.json of the copy the code was loaded from, and never re-read. A
|
|
23784
|
+
* copy replaced on disk under a live process must not move this number;
|
|
23785
|
+
* that divergence is what `installedVersion` is for. Before 2026-09-20 this
|
|
23786
|
+
* was a lazy disk read that would have followed such a swap silently.
|
|
23787
|
+
*/
|
|
23492
23788
|
runningVersion: string().nullable(),
|
|
23493
23789
|
/** Node.js runtime version the node's process runs on (`process.versions.node`). */
|
|
23494
23790
|
nodeRuntimeVersion: string().nullable(),
|
|
23495
23791
|
/** Active data-dir root version; null when booted from seed/workspace. */
|
|
23496
23792
|
activeVersion: string().nullable(),
|
|
23793
|
+
/**
|
|
23794
|
+
* Version of the root package in the data-root `current/` copy RIGHT NOW —
|
|
23795
|
+
* what the next boot would load if nothing is staged. Normally equal to
|
|
23796
|
+
* `runningVersion`; differs only when the copy on disk changed under the
|
|
23797
|
+
* live process. `null` when there is no data-root copy (baked seed or
|
|
23798
|
+
* workspace boot). Optional for version skew: an older provider omits it.
|
|
23799
|
+
*/
|
|
23800
|
+
installedVersion: string().nullable().optional(),
|
|
23801
|
+
/**
|
|
23802
|
+
* True when the code that would run after a restart is NOT the code running
|
|
23803
|
+
* now: a version is staged (`pendingVersion`), or `installedVersion` differs
|
|
23804
|
+
* from `runningVersion`. Derived on every read, never stored. This is the
|
|
23805
|
+
* one field that lets an operator or a script say "1.2.353 is installed and
|
|
23806
|
+
* will run after a restart" instead of reading it off a number that means
|
|
23807
|
+
* "installed". Optional for version skew.
|
|
23808
|
+
*/
|
|
23809
|
+
restartRequired: boolean().optional(),
|
|
23497
23810
|
/** N-1 version kept for rollback; null when no previous version exists. */
|
|
23498
23811
|
previousVersion: string().nullable(),
|
|
23499
23812
|
/** Version of the immutable baked seed closure (image fallback). */
|
|
@@ -23528,19 +23841,71 @@ var ServerPackageStatusSchema = object({
|
|
|
23528
23841
|
});
|
|
23529
23842
|
var ServerUpdateCheckResultSchema = object({
|
|
23530
23843
|
packageName: string(),
|
|
23844
|
+
/** Same meaning as on the status payload: what THIS process loaded. */
|
|
23531
23845
|
runningVersion: string().nullable(),
|
|
23532
23846
|
latestVersion: string().nullable(),
|
|
23847
|
+
/**
|
|
23848
|
+
* `latestVersion` is newer than `runningVersion` AND is not the version
|
|
23849
|
+
* already staged on this node. A staged-and-waiting version is not "an
|
|
23850
|
+
* update available" — applying it again is refused (`already-staged`), and
|
|
23851
|
+
* a button that announced "updating…" on this boolean then got refused
|
|
23852
|
+
* would be lying. It is reported through `pendingVersion` instead.
|
|
23853
|
+
*/
|
|
23533
23854
|
updateAvailable: boolean(),
|
|
23534
23855
|
checkedAtMs: number(),
|
|
23535
23856
|
/** Non-null when the registry lookup failed (offline, bad registry, …). */
|
|
23536
|
-
error: string().nullable()
|
|
23857
|
+
error: string().nullable(),
|
|
23858
|
+
/**
|
|
23859
|
+
* Version staged on this node and awaiting its restart, when one is. Before
|
|
23860
|
+
* 2026-09-20 a check answered `{runningVersion, updateAvailable:false}` for a
|
|
23861
|
+
* node whose staged closure had never booted, and the caller had no way to
|
|
23862
|
+
* see the difference. Optional for version skew.
|
|
23863
|
+
*/
|
|
23864
|
+
pendingVersion: string().nullable().optional(),
|
|
23865
|
+
/** See the status payload: staged, or installed-on-disk ≠ running. Optional for skew. */
|
|
23866
|
+
restartRequired: boolean().optional()
|
|
23537
23867
|
});
|
|
23868
|
+
/**
|
|
23869
|
+
* What an action DID — the discriminant `accepted` cannot carry. Before
|
|
23870
|
+
* 2026-09-20 `applyServerUpdate` answered `accepted:false` both for a refusal
|
|
23871
|
+
* where nothing was wrong (already current, already staged) and for a staging
|
|
23872
|
+
* install that died on `npm error code ECONNRESET`; the only difference was
|
|
23873
|
+
* prose in `message`, and an operator restarted a container on the strength of
|
|
23874
|
+
* it, booting the previous version.
|
|
23875
|
+
*
|
|
23876
|
+
* - `staged` — the closure is installed and validated; the node
|
|
23877
|
+
* restarts to apply it (`restarting:true`). NOTHING
|
|
23878
|
+
* runs the new code until that restart completes.
|
|
23879
|
+
* - `restart-scheduled` — a plain, version-preserving restart was accepted.
|
|
23880
|
+
* - `already-current` — the target IS the running version; nothing done.
|
|
23881
|
+
* - `refused` — dropped by a gate; `reason` names which.
|
|
23882
|
+
* - `failed` — attempted and did not land; `error` says why.
|
|
23883
|
+
*/
|
|
23884
|
+
var ServerUpdateOutcomeSchema = _enum([
|
|
23885
|
+
"staged",
|
|
23886
|
+
"restart-scheduled",
|
|
23887
|
+
"already-current",
|
|
23888
|
+
"refused",
|
|
23889
|
+
"failed"
|
|
23890
|
+
]);
|
|
23538
23891
|
var ServerUpdateActionResultSchema = object({
|
|
23539
23892
|
accepted: boolean(),
|
|
23540
23893
|
targetVersion: string().nullable(),
|
|
23541
23894
|
/** True when a graceful restart was scheduled to apply the change. */
|
|
23542
23895
|
restarting: boolean(),
|
|
23543
|
-
message: string()
|
|
23896
|
+
message: string(),
|
|
23897
|
+
/** See {@link ServerUpdateOutcomeSchema}. Optional for version skew. */
|
|
23898
|
+
outcome: ServerUpdateOutcomeSchema.optional(),
|
|
23899
|
+
/**
|
|
23900
|
+
* Stable, greppable cause for `refused` / `failed` (the engine's
|
|
23901
|
+
* `UpdateRefusalReason`, `staging-failed`, …). `null` on success.
|
|
23902
|
+
*/
|
|
23903
|
+
reason: string().nullable().optional(),
|
|
23904
|
+
/**
|
|
23905
|
+
* The failure itself, verbatim enough to act on (the npm output for a
|
|
23906
|
+
* staging install). Non-null only for `failed`.
|
|
23907
|
+
*/
|
|
23908
|
+
error: string().nullable().optional()
|
|
23544
23909
|
});
|
|
23545
23910
|
method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), ServerUpdateCheckResultSchema, {
|
|
23546
23911
|
kind: "mutation",
|
|
@@ -24649,6 +25014,18 @@ method(VectorDeclareIndexInputSchema, _void(), {
|
|
|
24649
25014
|
kind: "mutation",
|
|
24650
25015
|
auth: "admin"
|
|
24651
25016
|
}), method(VectorStatsInputSchema, VectorStatsResultSchema, { auth: "admin" });
|
|
25017
|
+
_enum([
|
|
25018
|
+
"queue-full",
|
|
25019
|
+
"camera-backoff",
|
|
25020
|
+
"sleeping",
|
|
25021
|
+
"camera-refused",
|
|
25022
|
+
"no-keyframe",
|
|
25023
|
+
"no-catalog-row",
|
|
25024
|
+
"unsupported",
|
|
25025
|
+
"unknown-device",
|
|
25026
|
+
"uid-missing"
|
|
25027
|
+
]);
|
|
25028
|
+
_enum(["deferred", "final"]);
|
|
24652
25029
|
var ClipSchema = object({
|
|
24653
25030
|
/** Opaque, provider-namespaced id. The default provider encodes the time
|
|
24654
25031
|
* window so `getClipPlayback` is self-contained (no event re-query). */
|
|
@@ -24723,29 +25100,455 @@ var ClipSchema = object({
|
|
|
24723
25100
|
holes: array(object({
|
|
24724
25101
|
startMs: number(),
|
|
24725
25102
|
endMs: number()
|
|
24726
|
-
})).optional()
|
|
25103
|
+
})).optional(),
|
|
25104
|
+
/**
|
|
25105
|
+
* A URL that MAY produce this clip's still, asked only for rows actually on
|
|
25106
|
+
* screen. The opposite of {@link ClipSchema.thumbnail}: that one is VOUCHED
|
|
25107
|
+
* (a JPEG is already on disk), this one is an offer. The route answers 200
|
|
25108
|
+
* with the image, or 204 with `x-camstack-reason` when it could not mint one
|
|
25109
|
+
* — a surface latches that refusal to the instant rather than retrying.
|
|
25110
|
+
*
|
|
25111
|
+
* Never both: a clip with a vouched `thumbnail` needs no mint.
|
|
25112
|
+
*/
|
|
25113
|
+
thumbnailMint: string().optional(),
|
|
25114
|
+
/**
|
|
25115
|
+
* Why no still will be produced for this clip RIGHT NOW — set when the
|
|
25116
|
+
* provider already knows, so the surface draws the glyph and the reason
|
|
25117
|
+
* instead of firing a mint that cannot succeed.
|
|
25118
|
+
*
|
|
25119
|
+
* `sleeping` — a standalone battery camera; a read would be a wake (D549 4).
|
|
25120
|
+
* `camera-refused` — the camera answered the CoverPreview with a refusal.
|
|
25121
|
+
* `no-keyframe` — the window holds no decodable I-frame (an event that sits
|
|
25122
|
+
* inside no file is the measured case).
|
|
25123
|
+
* `unsupported` — this source cannot mint stills at all.
|
|
25124
|
+
*/
|
|
25125
|
+
thumbnailUnavailable: object({ reason: _enum([
|
|
25126
|
+
"sleeping",
|
|
25127
|
+
"camera-refused",
|
|
25128
|
+
"no-keyframe",
|
|
25129
|
+
"unsupported"
|
|
25130
|
+
]) }).optional(),
|
|
25131
|
+
/**
|
|
25132
|
+
* When the catalog this row came from was last CONFIRMED against the device.
|
|
25133
|
+
* Absent means "this row was read live". A persisted catalog served while a
|
|
25134
|
+
* camera sleeps carries the age it really has — a cached list is never drawn
|
|
25135
|
+
* as current (D549 13).
|
|
25136
|
+
*/
|
|
25137
|
+
catalogAsOf: number().optional(),
|
|
25138
|
+
/**
|
|
25139
|
+
* The camera's OWN type strings for this clip, all of them, unmapped
|
|
25140
|
+
* (`md`, `people`, `dog_cat`, `sched`, …). Kept beside {@link labels}
|
|
25141
|
+
* because a firmware inventing a type must not vanish: the mapping into our
|
|
25142
|
+
* filter vocabulary is lossy on purpose and this is the lossless copy
|
|
25143
|
+
* (D549 20).
|
|
25144
|
+
*/
|
|
25145
|
+
nativeTypes: array(string()).optional(),
|
|
25146
|
+
/**
|
|
25147
|
+
* What the subject DID — `crossline`, `intrude`, `loitering`. A behaviour
|
|
25148
|
+
* travels BESIDE a class, never instead of one, and the class filter ignores
|
|
25149
|
+
* it: "a person crossed a line" is still a person (D549 20).
|
|
25150
|
+
*/
|
|
25151
|
+
behaviours: array(string()).optional(),
|
|
25152
|
+
/**
|
|
25153
|
+
* The same recording as two files — the sub twin (what the row and its
|
|
25154
|
+
* thumbnail are) and its main twin, matched at listing time so a quality
|
|
25155
|
+
* change never re-searches the camera (D549 15). `getClipPlayback`'s
|
|
25156
|
+
* `profile` picks between them: `low | mid` → sub, `high` → main.
|
|
25157
|
+
*/
|
|
25158
|
+
streams: object({
|
|
25159
|
+
sub: object({
|
|
25160
|
+
id: string(),
|
|
25161
|
+
bytes: number().optional()
|
|
25162
|
+
}).optional(),
|
|
25163
|
+
main: object({
|
|
25164
|
+
id: string(),
|
|
25165
|
+
bytes: number().optional()
|
|
25166
|
+
}).optional()
|
|
25167
|
+
}).optional(),
|
|
25168
|
+
/** The camera says it holds a sub-stream copy of this recording. */
|
|
25169
|
+
supportSub: boolean().optional(),
|
|
25170
|
+
/**
|
|
25171
|
+
* Whether this row has bytes behind it. ABSENT means yes — every clip that
|
|
25172
|
+
* IS a file is playable, and only a source that lists EVENTS can produce a
|
|
25173
|
+
* row with nothing to play (the measured case: 1 of 29 hub events on 3628
|
|
25174
|
+
* fell inside no file). Such a row is shown, never dropped and never offered
|
|
25175
|
+
* as playable-then-failing (D549 19).
|
|
25176
|
+
*/
|
|
25177
|
+
playable: boolean().optional(),
|
|
25178
|
+
/** Why {@link playable} is false, verbatim (`no-file-for-window`). */
|
|
25179
|
+
unplayableReason: string().optional(),
|
|
25180
|
+
/**
|
|
25181
|
+
* This clip is STILL BEING WRITTEN, so {@link ClipSchema.timeRange}`.endMs`
|
|
25182
|
+
* is not its end.
|
|
25183
|
+
*
|
|
25184
|
+
* Absent — the common case — means the row is closed and its `endMs` is the
|
|
25185
|
+
* end of the recording. Present and `true` means the source told us the file
|
|
25186
|
+
* has no end yet, and the `endMs` we carry is whatever the camera's index
|
|
25187
|
+
* entry happened to hold: on a Reolink E1 Outdoor PoE (592, measured
|
|
25188
|
+
* 2026-09-20) the newest file `…_192927_000000_…_0.mp4` reported an `endTime`
|
|
25189
|
+
* of 19:29:56 and STILL reported it eight minutes later, while the file went
|
|
25190
|
+
* on growing. A surface that drew 29 s there was lying about a clip that
|
|
25191
|
+
* plays for minutes, on the one row the operator looks at first.
|
|
25192
|
+
*
|
|
25193
|
+
* `endMs` is deliberately still a number: it is the best bound anything has
|
|
25194
|
+
* for a mint window or a byte fetch, and every consumer already requires it.
|
|
25195
|
+
* This flag says what it is WORTH, and a duration is not drawn from it.
|
|
25196
|
+
*/
|
|
25197
|
+
inProgress: boolean().optional()
|
|
24727
25198
|
});
|
|
24728
25199
|
var ClipPlaybackSchema = object({
|
|
24729
|
-
/**
|
|
25200
|
+
/**
|
|
25201
|
+
* A media URL through the hub data-plane. {@link ClipPlaybackSchema.format}
|
|
25202
|
+
* says what kind — an HLS master playlist for a recording-derived clip, a
|
|
25203
|
+
* progressive MP4 for a native file the vendor addon muxed and serves with
|
|
25204
|
+
* `Range`. The URL is NOT a credential: both planes are registered
|
|
25205
|
+
* `access: 'authenticated'` and the hub's `/addon/<id>/<prefix>` proxy takes
|
|
25206
|
+
* the session cookie, so nothing is appended to it (D549 22).
|
|
25207
|
+
*/
|
|
24730
25208
|
playbackUrl: string(),
|
|
25209
|
+
/**
|
|
25210
|
+
* How to play {@link playbackUrl}. Absent means `hls` — the shape every
|
|
25211
|
+
* existing consumer already assumes. A player that branches on this is the
|
|
25212
|
+
* one change a native clip needs; a player that ignores it will hand an MP4
|
|
25213
|
+
* to hls.js and fail parsing it as a manifest.
|
|
25214
|
+
*/
|
|
25215
|
+
format: _enum(["hls", "mp4"]).optional(),
|
|
25216
|
+
/**
|
|
25217
|
+
* Which twin was actually served. A clip that holds only one stream answers
|
|
25218
|
+
* with the one it has, and the surface SAYS so — a missing main twin is
|
|
25219
|
+
* never served silently as if it were the asked-for quality (D549 15).
|
|
25220
|
+
*/
|
|
25221
|
+
served: CamProfileSchema.optional(),
|
|
24731
25222
|
/** Optional LAN/remote alternates for the same clip. */
|
|
24732
25223
|
playbackEndpoints: array(string()).optional(),
|
|
24733
25224
|
token: string().optional()
|
|
24734
25225
|
});
|
|
25226
|
+
/**
|
|
25227
|
+
* Why a source cannot answer right now — per SOURCE, never fleet-wide.
|
|
25228
|
+
*
|
|
25229
|
+
* `ok` is the only state whose clip list may be read as complete. The other
|
|
25230
|
+
* three exist because an empty list from a sleeping camera reads as "this
|
|
25231
|
+
* camera has no recordings", which is the defect this whole line of work is
|
|
25232
|
+
* about: a battery camera nobody woke (`sleeping`), a camera that could not be
|
|
25233
|
+
* reached at all (`unreachable`, also what a provider that THREW reports), a
|
|
25234
|
+
* camera whose SD card is not mounted (`no-storage`, measured on 640 —
|
|
25235
|
+
* `HddInfo mount 0`, honestly nothing to list rather than "no clips"), and a
|
|
25236
|
+
* camera whose OWN index disagrees with its OWN calendar (`index-empty`,
|
|
25237
|
+
* measured on 618: the calendar marks 3–20 September, days 6–20 list zero
|
|
25238
|
+
* files on both streams and both filters, with 177 GB free). That last one is
|
|
25239
|
+
* a defect ON THE CAMERA, and the only honest thing a provider can do is say
|
|
25240
|
+
* which days it asked for and got nothing — "no clips" would be a lie about a
|
|
25241
|
+
* card that is full of them.
|
|
25242
|
+
*/
|
|
25243
|
+
/**
|
|
25244
|
+
* The operator's authorisation to WAKE a sleeping camera for one clip read.
|
|
25245
|
+
*
|
|
25246
|
+
* ONE value, absent by default, and it is a `force`-shaped operator signal in
|
|
25247
|
+
* exactly the sense `snapshot-wake-gate.ts` uses the word: *"`snapshot.getSnapshot`'s
|
|
25248
|
+
* `force` flag, and nothing else… a background caller must never set it…
|
|
25249
|
+
* Stale but honest beats woken"*. A scheduler, a retry, a reconcile and a
|
|
25250
|
+
* prefetch never set it; a surface sets it only behind the same confirm the
|
|
25251
|
+
* "Wake and refresh" gesture uses, and it is refused below 15 % battery
|
|
25252
|
+
* exactly as that gesture is.
|
|
25253
|
+
*
|
|
25254
|
+
* The gate is decided BEFORE `getApi()`, because on UDP the login IS the wake
|
|
25255
|
+
* (D549) — a read that opened a session and then checked would have woken the
|
|
25256
|
+
* camera to find out it was not allowed to.
|
|
25257
|
+
*
|
|
25258
|
+
* **One authorised yes is one wake.** `next-natural` — take the clip the next
|
|
25259
|
+
* time the camera is awake for its own reasons — is deliberately not a member:
|
|
25260
|
+
* it was proposed, it is free on the battery, and the operator declined it on
|
|
25261
|
+
* 2026-09-20 (*"Quando un export viene richiesto si sveglia la camera."*,
|
|
25262
|
+
* D558 "Considered and not taken").
|
|
25263
|
+
*/
|
|
25264
|
+
var ClipWakeSchema = _enum(["authorised"]);
|
|
25265
|
+
/**
|
|
25266
|
+
* A clip's finished bytes, inline — the twin of `recordingExport.readExportBytes`.
|
|
25267
|
+
*
|
|
25268
|
+
* `bytes` is the DECODED length, so nobody infers it from the base64 length,
|
|
25269
|
+
* and `served` says which twin the caller actually got.
|
|
25270
|
+
*/
|
|
25271
|
+
var ClipBytesSchema = object({
|
|
25272
|
+
base64: string(),
|
|
25273
|
+
contentType: string(),
|
|
25274
|
+
/** Suggested filename, extension included. */
|
|
25275
|
+
name: string(),
|
|
25276
|
+
bytes: number().int().nonnegative(),
|
|
25277
|
+
/**
|
|
25278
|
+
* Which twin was actually served — the same contract
|
|
25279
|
+
* {@link ClipPlaybackSchema.served} carries, and REQUIRED here because the
|
|
25280
|
+
* export record persists it: a row read a week later must say the same thing
|
|
25281
|
+
* the panel said at the moment of the tap. A missing main twin is never
|
|
25282
|
+
* served silently as if it were the asked-for quality (D549 15).
|
|
25283
|
+
*/
|
|
25284
|
+
served: CamProfileSchema,
|
|
25285
|
+
/**
|
|
25286
|
+
* The DECODED duration of the delivered file, when the fetch measured one.
|
|
25287
|
+
*
|
|
25288
|
+
* A clip fetch verifies its own completion against the catalog row and
|
|
25289
|
+
* retries a materially short pass (D568); this is that measurement, carried
|
|
25290
|
+
* so a consumer can say the same thing rather than re-deriving it. Absent
|
|
25291
|
+
* when the producer did not measure — never zero, which would say the file
|
|
25292
|
+
* is empty.
|
|
25293
|
+
*/
|
|
25294
|
+
durationMs: number().positive().optional()
|
|
25295
|
+
});
|
|
25296
|
+
/**
|
|
25297
|
+
* Where a clip's STREAM can be dialled (D597) — the answer to
|
|
25298
|
+
* {@link videoclipsCapability.methods.dialClipStream}.
|
|
25299
|
+
*
|
|
25300
|
+
* `url` is plain `http://` on the provider's own token-gated listener, one
|
|
25301
|
+
* shot, short-lived. It is NOT the hub-proxied `/addon/<id>/clip-stream/…`
|
|
25302
|
+
* path: that plane takes only a user credential, which an addon does not
|
|
25303
|
+
* hold, and the framework offers no addon→addon byte transport — the one
|
|
25304
|
+
* precedent is the broker's own restream URLs (`getStreamWithCodec`), which
|
|
25305
|
+
* a consumer dials directly, and this is that precedent one addon over.
|
|
25306
|
+
*/
|
|
25307
|
+
/**
|
|
25308
|
+
* The audio a clip stream can be asked for, and the audio it carries.
|
|
25309
|
+
*
|
|
25310
|
+
* The camera stores AAC and no WebRTC session speaks it, so a stream that
|
|
25311
|
+
* carries sound carries it TRANSCODED, muxed as a second track beside the
|
|
25312
|
+
* video by the one ffmpeg the provider already runs (D600). `opus` is
|
|
25313
|
+
* 48 kHz mono, `pcmu` is 8 kHz µ-law — the two codecs a broker session
|
|
25314
|
+
* negotiates — and `none` is a stream asked for, or served, without sound.
|
|
25315
|
+
*/
|
|
25316
|
+
var ClipStreamAudioSchema = _enum([
|
|
25317
|
+
"opus",
|
|
25318
|
+
"pcmu",
|
|
25319
|
+
"none"
|
|
25320
|
+
]);
|
|
25321
|
+
/**
|
|
25322
|
+
* Why a stream that was ASKED for sound is not carrying it (D600).
|
|
25323
|
+
*
|
|
25324
|
+
* Only ever set beside `servedAudio: 'none'` after a non-`none` ask. Absent
|
|
25325
|
+
* means the ask was honoured, or there was no ask.
|
|
25326
|
+
*
|
|
25327
|
+
* - `not-requested` — the caller asked for `none`.
|
|
25328
|
+
* - `unsupported-ask` — the provider cannot produce that codec.
|
|
25329
|
+
*
|
|
25330
|
+
* Whether the RECORDING has sound at all is not knowable here: the camera
|
|
25331
|
+
* declares no audio track before its first frame arrives. That answer is in
|
|
25332
|
+
* the stream itself — an fMP4 with no audio track — and the broker reads it
|
|
25333
|
+
* there. A dial that says `opus` promises the codec, never the content.
|
|
25334
|
+
*/
|
|
25335
|
+
var ClipStreamAudioReasonSchema = _enum(["not-requested", "unsupported-ask"]);
|
|
25336
|
+
var ClipStreamDialSchema = object({
|
|
25337
|
+
url: string().min(1),
|
|
25338
|
+
/** After this the token is gone and the URL answers 404 `dial-expired`. */
|
|
25339
|
+
expiresAtMs: number(),
|
|
25340
|
+
/** What the stream IS — a consumer that cannot honour it must not dial. */
|
|
25341
|
+
transport: literal("forward-only"),
|
|
25342
|
+
/**
|
|
25343
|
+
* Which twin the stream ACTUALLY carries — not what was asked for.
|
|
25344
|
+
*
|
|
25345
|
+
* The stream serves every profile (D599), and a recording whose main twin
|
|
25346
|
+
* does not exist is streamed as its sub copy, which this field reports as
|
|
25347
|
+
* `low`. That is the whole reason the dial no longer refuses `high`:
|
|
25348
|
+
* stating what was served is what makes accepting honest, where a silent
|
|
25349
|
+
* substitution would be the 33x lie D576 forbids. Stated rather than
|
|
25350
|
+
* assumed, the way {@link ClipPlaybackSchema.served} is (D549 15).
|
|
25351
|
+
*/
|
|
25352
|
+
served: CamProfileSchema,
|
|
25353
|
+
/**
|
|
25354
|
+
* Which audio the stream will ACTUALLY carry — `served`'s companion for
|
|
25355
|
+
* sound, and the same reasoning (D599, D600).
|
|
25356
|
+
*
|
|
25357
|
+
* The broker asks for the codec its WebRTC session negotiated, and the
|
|
25358
|
+
* provider either muxes that codec or carries none. Stating it is what
|
|
25359
|
+
* lets the broker wire the matching sink before the first byte, and what
|
|
25360
|
+
* keeps a session from being handed a codec it cannot send — the audio
|
|
25361
|
+
* shape of the substitution `served` exists to prevent.
|
|
25362
|
+
*
|
|
25363
|
+
* It is a promise about the CODEC, not about the content: a recording with
|
|
25364
|
+
* no microphone track answers `opus` here and then arrives with no audio
|
|
25365
|
+
* track at all. That second answer is in the stream, and the broker reads
|
|
25366
|
+
* it from the `moov`.
|
|
25367
|
+
*/
|
|
25368
|
+
servedAudio: ClipStreamAudioSchema,
|
|
25369
|
+
/** Why `servedAudio` is `none` although sound was asked for. */
|
|
25370
|
+
audioReason: ClipStreamAudioReasonSchema.optional()
|
|
25371
|
+
});
|
|
25372
|
+
var ClipSourceAvailabilitySchema = object({
|
|
25373
|
+
state: _enum([
|
|
25374
|
+
"ok",
|
|
25375
|
+
"sleeping",
|
|
25376
|
+
"unreachable",
|
|
25377
|
+
"no-storage",
|
|
25378
|
+
"index-empty"
|
|
25379
|
+
]),
|
|
25380
|
+
/** Free text, shown verbatim. Names the camera's own refusal when there is one. */
|
|
25381
|
+
reason: string().optional(),
|
|
25382
|
+
/** When this source's catalog was last CONFIRMED. A cached list is never
|
|
25383
|
+
* drawn as current: the surface shows the age whenever it is older than the
|
|
25384
|
+
* refresh interval. */
|
|
25385
|
+
catalogAsOf: number().optional()
|
|
25386
|
+
});
|
|
25387
|
+
/**
|
|
25388
|
+
* One SOURCE of clips for a camera — a row of the picker, and the namespace
|
|
25389
|
+
* every clip id from it is prefixed with (`analytics`,
|
|
25390
|
+
* `native:reolink:onboard`, `hksv`, …).
|
|
25391
|
+
*
|
|
25392
|
+
* A provider lists the sources IT serves for that device, and answers for each
|
|
25393
|
+
* of them whether it can answer at all. A provider with nothing to offer on a
|
|
25394
|
+
* camera returns `[]` — it is not that camera's business.
|
|
25395
|
+
*/
|
|
25396
|
+
var ClipSourceSchema = object({
|
|
25397
|
+
/** The value this source stamps on {@link ClipSchema.source}, and the prefix
|
|
25398
|
+
* of every clip id it mints. `getClipPlayback` routes on it. */
|
|
25399
|
+
source: string(),
|
|
25400
|
+
/** Operator-facing name of the source ("CamStack recordings", "SD card"). */
|
|
25401
|
+
label: string(),
|
|
25402
|
+
/**
|
|
25403
|
+
* The addon that SERVES this row.
|
|
25404
|
+
*
|
|
25405
|
+
* A surface cannot otherwise resolve a source to who answers it, and the
|
|
25406
|
+
* alternative — a `native:reolink:* → provider-reolink` table inside the
|
|
25407
|
+
* widget — is a second authority on provider identity living in the one
|
|
25408
|
+
* package with no business knowing it, wrong the day a third source appears
|
|
25409
|
+
* (D557). One addon may serve SEVERAL sources, which is why the per-device
|
|
25410
|
+
* switch is keyed by SOURCE and not by this (D555) — `addon-provider-reolink`
|
|
25411
|
+
* served a hub child two of them until the two views were measured to be one
|
|
25412
|
+
* store read twice (D555) and then read ONE way (D565).
|
|
25413
|
+
*
|
|
25414
|
+
* Optional for version skew only. The collection dispatcher stamps it from
|
|
25415
|
+
* the registry, so a row that travelled through the fan-out carries the
|
|
25416
|
+
* authoritative id whatever the provider filled in.
|
|
25417
|
+
*/
|
|
25418
|
+
addonId: string().optional(),
|
|
25419
|
+
availability: ClipSourceAvailabilitySchema
|
|
25420
|
+
});
|
|
24735
25421
|
DeviceType.Camera, method(object({
|
|
24736
25422
|
deviceId: number(),
|
|
24737
25423
|
since: number(),
|
|
24738
25424
|
until: number(),
|
|
24739
|
-
limit: number().int().positive().optional()
|
|
25425
|
+
limit: number().int().positive().optional(),
|
|
25426
|
+
/**
|
|
25427
|
+
* WHICH provider to ask — the `addonId` a {@link ClipSourceSchema} row
|
|
25428
|
+
* carries, never a source id and never a list. **Required** (D554 amended).
|
|
25429
|
+
*
|
|
25430
|
+
* A provider the device is not bound to is refused by name rather than
|
|
25431
|
+
* answered by another one (D552's `rejectUnresolvedAddonPin` rule).
|
|
25432
|
+
*
|
|
25433
|
+
* It was optional, documented as "absent means the device's BOUND
|
|
25434
|
+
* provider, which is CamStack on every camera". No code implemented
|
|
25435
|
+
* that. Measured on the live hub 2026-09-20 — device 592, bound to
|
|
25436
|
+
* `recorder` AND `provider-reolink` — a bare call with `limit: 3`
|
|
25437
|
+
* answered SIX rows, three from each source, merged newest-first:
|
|
25438
|
+
* `device-collection-dispatch.ts` simply left the fan-out un-narrowed,
|
|
25439
|
+
* so absence bought the union this method exists not to be, and
|
|
25440
|
+
* `limit` meant `limit × sources`.
|
|
25441
|
+
*
|
|
25442
|
+
* There is nothing to restore the default to. `getBindings` answers a
|
|
25443
|
+
* collection cap with a DERIVED, PLURAL set (D554 amended, step 0);
|
|
25444
|
+
* `setWrapperActive` — the singleton authority that could name one —
|
|
25445
|
+
* throws for a collection cap by design. Naming CamStack here instead
|
|
25446
|
+
* would privilege one addon by id inside a surface whose premise is
|
|
25447
|
+
* that sources are peers, and would be wrong on the first camera with
|
|
25448
|
+
* no recorder binding. So absence is REFUSED, in the schema, where the
|
|
25449
|
+
* generated types make it unomittable rather than merely discouraged.
|
|
25450
|
+
*
|
|
25451
|
+
* The default belongs to the SURFACE, which has the `listSources` rows
|
|
25452
|
+
* and can say which one it picked (D569 § 1–3; the viewer already
|
|
25453
|
+
* always sends this).
|
|
25454
|
+
*
|
|
25455
|
+
* It replaced `sources?: string[]`, a VIEW filter over source ids that
|
|
25456
|
+
* assumed the answer was a fan-out over everything a camera has. The
|
|
25457
|
+
* operator settled otherwise on 2026-09-20 — *"l'utilizzatore è uno
|
|
25458
|
+
* solo"* — so the list is asked of one provider at a time and there is
|
|
25459
|
+
* nothing to filter out of it.
|
|
25460
|
+
*/
|
|
25461
|
+
provider: string().min(1)
|
|
24740
25462
|
}), array(ClipSchema).readonly(), {
|
|
24741
25463
|
kind: "query",
|
|
24742
|
-
auth: "
|
|
25464
|
+
auth: "protected"
|
|
25465
|
+
}), method(object({ deviceId: number() }), array(ClipSourceSchema).readonly(), {
|
|
25466
|
+
kind: "query",
|
|
25467
|
+
auth: "protected"
|
|
24743
25468
|
}), method(object({
|
|
24744
25469
|
deviceId: number(),
|
|
24745
|
-
clipId: string()
|
|
25470
|
+
clipId: string(),
|
|
25471
|
+
/**
|
|
25472
|
+
* Which twin to serve, on the ONE quality scale the system already has
|
|
25473
|
+
* (`CamProfileSchema`). `low | mid` → the sub file, `high` → the main
|
|
25474
|
+
* twin; both ids are already on the row so this never re-searches the
|
|
25475
|
+
* camera. Absent means the provider's own default (the sub file, which
|
|
25476
|
+
* every source is measured to hold).
|
|
25477
|
+
*
|
|
25478
|
+
* `auto` is deliberately NOT accepted here: a stored file has no
|
|
25479
|
+
* broker session, so the adaptive tier cannot be resolved for it. The
|
|
25480
|
+
* viewer resolves `auto` to a profile the same way live does, before
|
|
25481
|
+
* it calls (D549 15).
|
|
25482
|
+
*/
|
|
25483
|
+
profile: CamProfileSchema.optional()
|
|
24746
25484
|
}), ClipPlaybackSchema, {
|
|
24747
25485
|
kind: "query",
|
|
24748
|
-
auth: "
|
|
25486
|
+
auth: "protected"
|
|
25487
|
+
}), optionalMethod(object({
|
|
25488
|
+
deviceId: number(),
|
|
25489
|
+
clipId: string().min(1),
|
|
25490
|
+
/**
|
|
25491
|
+
* WHICH provider holds the bytes — the `addonId` a
|
|
25492
|
+
* {@link ClipSourceSchema} row carries. **Required**, for the reason
|
|
25493
|
+
* `listClips` states one method above and for a second one this method
|
|
25494
|
+
* learned the hard way.
|
|
25495
|
+
*
|
|
25496
|
+
* The caller is the stream broker, and the broker lives in
|
|
25497
|
+
* `addon-pipeline` — the same addon that registers the RECORDER's
|
|
25498
|
+
* videoclips provider. With no provider named, the in-process
|
|
25499
|
+
* resolution handed it its own sibling, which implements this method
|
|
25500
|
+
* solely to explain that an analytics visit has no file behind it. So
|
|
25501
|
+
* every onboard clip answered with that sentence, a flash of video and
|
|
25502
|
+
* nothing more, while the SAME call from outside the addon reached the
|
|
25503
|
+
* right provider and returned the bytes (measured on 3628,
|
|
25504
|
+
* 2026-09-21).
|
|
25505
|
+
*/
|
|
25506
|
+
provider: string().min(1),
|
|
25507
|
+
/**
|
|
25508
|
+
* Which twin to fetch, on the mapping D549 15 already fixed:
|
|
25509
|
+
* `low | mid` → the sub file, `high` → the main twin. `auto` is not
|
|
25510
|
+
* accepted here for the same reason it is not accepted by
|
|
25511
|
+
* `getClipPlayback` — a stored file has no broker session, so the
|
|
25512
|
+
* adaptive tier cannot be resolved for it.
|
|
25513
|
+
*/
|
|
25514
|
+
profile: CamProfileSchema.optional(),
|
|
25515
|
+
/**
|
|
25516
|
+
* The CALLER's byte bound, so an over-size clip is refused before it is
|
|
25517
|
+
* read and encoded rather than after. Capped by
|
|
25518
|
+
* {@link VIDEOCLIPS_MAX_READ_BYTES} whatever is passed; absent means
|
|
25519
|
+
* that ceiling.
|
|
25520
|
+
*/
|
|
25521
|
+
maxBytes: number().int().positive().optional(),
|
|
25522
|
+
/**
|
|
25523
|
+
* The operator's authorisation to wake a sleeping camera for this
|
|
25524
|
+
* read. Absent — the default — means a sleeping standalone battery
|
|
25525
|
+
* camera is REFUSED by name, before any session is opened.
|
|
25526
|
+
*/
|
|
25527
|
+
wake: ClipWakeSchema.optional()
|
|
25528
|
+
}), ClipBytesSchema, {
|
|
25529
|
+
kind: "query",
|
|
25530
|
+
auth: "protected"
|
|
25531
|
+
}), optionalMethod(object({
|
|
25532
|
+
deviceId: number(),
|
|
25533
|
+
clipId: string().min(1),
|
|
25534
|
+
/** WHICH provider holds the camera — see `readClipBytes.provider`. */
|
|
25535
|
+
provider: string().min(1),
|
|
25536
|
+
/** Which twin — `high` → the main file, everything else the sub (D599). */
|
|
25537
|
+
profile: CamProfileSchema.optional(),
|
|
25538
|
+
/**
|
|
25539
|
+
* Which audio codec the caller's session negotiated, so the provider
|
|
25540
|
+
* can mux it (D600). The ask travels on the DIAL because the mux is
|
|
25541
|
+
* spawned once, before the first byte, and cannot gain a track later.
|
|
25542
|
+
*
|
|
25543
|
+
* ABSENT IS `none`, never a guess: a caller that does not state an
|
|
25544
|
+
* ask is served the video-only stream that shipped first, so a broker
|
|
25545
|
+
* older than this field keeps working unchanged (D382 — an unstated
|
|
25546
|
+
* ask is zero).
|
|
25547
|
+
*/
|
|
25548
|
+
audio: ClipStreamAudioSchema.optional()
|
|
25549
|
+
}), ClipStreamDialSchema, {
|
|
25550
|
+
kind: "query",
|
|
25551
|
+
auth: "protected"
|
|
24749
25552
|
});
|
|
24750
25553
|
/**
|
|
24751
25554
|
* Optional client-side hints sent at session creation to help the provider
|
|
@@ -26997,6 +27800,346 @@ var dayNightCapability = {
|
|
|
26997
27800
|
volatileStateFields: ["lastFetchedAt"]
|
|
26998
27801
|
};
|
|
26999
27802
|
/**
|
|
27803
|
+
* Vendor-neutral **onboard** recording + storage cap — what the CAMERA
|
|
27804
|
+
* writes to the CAMERA's own card, on the camera's own schedule.
|
|
27805
|
+
*
|
|
27806
|
+
* This is NOT `recording.cap.ts`. That one is CamStack's recorder: our
|
|
27807
|
+
* footage ledger, our storage locations, our retention. This one has a
|
|
27808
|
+
* different authority — the camera's firmware — and per D62 it stores
|
|
27809
|
+
* nothing of its own. Every value here is read from the camera and every
|
|
27810
|
+
* write goes back to the camera; there is no CamStack-side mirror that
|
|
27811
|
+
* could disagree with the device.
|
|
27812
|
+
*
|
|
27813
|
+
* ## One shape, two firmwares
|
|
27814
|
+
*
|
|
27815
|
+
* Measured 2026-09-22 against the live fleet:
|
|
27816
|
+
*
|
|
27817
|
+
* | fact | Hikvision (ISAPI) | Reolink (Baichuan) |
|
|
27818
|
+
* | --- | --- | --- |
|
|
27819
|
+
* | storage | `ContentMgmt/Storage` `<hdd>` rows: status, capacity, freeSpace (MB) | `getHddInfoList` (cmd 102): `mount`, `format`, `capacity` GB + `capacityM` MB remainder |
|
|
27820
|
+
* | tracks | several (101 **and** 103 on both 1436 and 3833), each with its own schedule | one per channel |
|
|
27821
|
+
* | schedule | per track, 7 `ScheduleAction` blocks: DayOfWeek + TimeOfDay range + ONE `ActionRecordingMode` | per trigger type, a 168-char weekly HOUR mask |
|
|
27822
|
+
* | triggers | `CMR`, `MOTION` | `Normal`, `MD`, `people`, `vehicle`, `dog_cat`, `crossline`, `intrude`, `loitering` |
|
|
27823
|
+
* | pre-record | `PreRecordTimeSeconds` | `preRecordTime` |
|
|
27824
|
+
* | post-record | `PostRecordTimeSeconds` | `recordDelayTime` |
|
|
27825
|
+
* | overwrite | per track `LoopEnable` | `cycle`, with `cycleList` enumerating the accepted values |
|
|
27826
|
+
* | segment length | not exposed on V5.7.1 | `packageTime` (minutes) |
|
|
27827
|
+
*
|
|
27828
|
+
* The two schedule models look different and are the same thing in
|
|
27829
|
+
* different coordinates: both answer "for this trigger, during which
|
|
27830
|
+
* weekly windows does the camera record". {@link RecordWindow} is that
|
|
27831
|
+
* question in one shape — Hikvision's ranges map straight onto it,
|
|
27832
|
+
* Reolink's mask expands into hour-aligned windows.
|
|
27833
|
+
*
|
|
27834
|
+
* ## Union, not intersection
|
|
27835
|
+
*
|
|
27836
|
+
* **The same fields exist on every camera.** What differs per device is
|
|
27837
|
+
* which VALUES that device accepts, and that is what {@link
|
|
27838
|
+
* RecordingOnboardOptions} reports — a `{ readable, writable, reason }`
|
|
27839
|
+
* per field plus the schedule's own limits. A control a camera cannot
|
|
27840
|
+
* honour is rendered DISABLED WITH ITS REASON, never missing and never
|
|
27841
|
+
* dead: disabled must not look like broken.
|
|
27842
|
+
*
|
|
27843
|
+
* ## Refusal by name
|
|
27844
|
+
*
|
|
27845
|
+
* A write a camera cannot honour is refused with a sentence the operator
|
|
27846
|
+
* can read — never accepted and dropped. Both providers refuse through
|
|
27847
|
+
* {@link describeOnboardRefusal}, so the vocabulary is one function and
|
|
27848
|
+
* one test, not two hand-written vendor opinions.
|
|
27849
|
+
*
|
|
27850
|
+
* Follows the D14 `deviceConfig` archetype (see `stream-params.cap.ts`):
|
|
27851
|
+
* `getOptions` advertises per-camera availability, `getStatus` (auto-
|
|
27852
|
+
* injected from `status`) reports the live values, and a single
|
|
27853
|
+
* `setSettings` mutation applies a partial change. No hand-written
|
|
27854
|
+
* settings-contribution methods.
|
|
27855
|
+
*/
|
|
27856
|
+
/**
|
|
27857
|
+
* What makes the camera start recording during a window.
|
|
27858
|
+
*
|
|
27859
|
+
* The union of both vendors' vocabularies. `continuous` is Hikvision's
|
|
27860
|
+
* `CMR` and Reolink's `Normal`; `motion` is `MOTION` / `MD`. The
|
|
27861
|
+
* object-class triggers are Reolink-only today and the smart-event ones
|
|
27862
|
+
* (`lineCrossing`, `intrusion`, `loitering`) are Reolink-only on the
|
|
27863
|
+
* firmwares measured — a camera that cannot record on a trigger simply
|
|
27864
|
+
* does not list it in `options.schedule.triggers`, and a window naming
|
|
27865
|
+
* it is REFUSED, not dropped.
|
|
27866
|
+
*/
|
|
27867
|
+
var RecordTriggerSchema = _enum([
|
|
27868
|
+
"continuous",
|
|
27869
|
+
"motion",
|
|
27870
|
+
"person",
|
|
27871
|
+
"vehicle",
|
|
27872
|
+
"animal",
|
|
27873
|
+
"lineCrossing",
|
|
27874
|
+
"intrusion",
|
|
27875
|
+
"loitering",
|
|
27876
|
+
"alarmInput"
|
|
27877
|
+
]);
|
|
27878
|
+
/**
|
|
27879
|
+
* One weekly recording window: "on `day`, from `startMinute` to
|
|
27880
|
+
* `endMinute`, record on `trigger`".
|
|
27881
|
+
*
|
|
27882
|
+
* `day` is 0 = Monday … 6 = Sunday (ISO order, which is also the order
|
|
27883
|
+
* both firmwares enumerate). Minutes are local camera time since
|
|
27884
|
+
* midnight; `endMinute` may be 1440, meaning end of day — that is
|
|
27885
|
+
* Hikvision's literal `24:00` and Reolink's 24th mask slot, and
|
|
27886
|
+
* collapsing it to 0 would turn a whole-day window into an empty one.
|
|
27887
|
+
*/
|
|
27888
|
+
var RecordWindowSchema = object({
|
|
27889
|
+
trigger: RecordTriggerSchema,
|
|
27890
|
+
day: number().int().min(0).max(6),
|
|
27891
|
+
startMinute: number().int().min(0).max(1439),
|
|
27892
|
+
endMinute: number().int().min(1).max(1440)
|
|
27893
|
+
});
|
|
27894
|
+
/** Status of one physical volume, as the camera itself describes it. */
|
|
27895
|
+
var OnboardStorageVolumeSchema = object({
|
|
27896
|
+
/** The camera's own id for the volume (`hdd/id`, Reolink `HddInfo/number`). */
|
|
27897
|
+
id: string(),
|
|
27898
|
+
/** The camera's own name for it, when it gives one (`hddName`). */
|
|
27899
|
+
label: string().optional(),
|
|
27900
|
+
status: _enum([
|
|
27901
|
+
"ok",
|
|
27902
|
+
"unformatted",
|
|
27903
|
+
"error",
|
|
27904
|
+
"offline",
|
|
27905
|
+
"unknown"
|
|
27906
|
+
]),
|
|
27907
|
+
/**
|
|
27908
|
+
* Total size in MB, or **null when the camera did not say**.
|
|
27909
|
+
*
|
|
27910
|
+
* Never 0 for an unreadable value: a measurement that failed is not a
|
|
27911
|
+
* measurement (D393), and a card whose size is unknown must not be
|
|
27912
|
+
* rendered as a card of size zero.
|
|
27913
|
+
*/
|
|
27914
|
+
capacityMb: number().nullable(),
|
|
27915
|
+
/**
|
|
27916
|
+
* Free space in MB, or null when unknown.
|
|
27917
|
+
*
|
|
27918
|
+
* **Not a proxy for "has footage".** Measured 2026-09-22: 1436 and
|
|
27919
|
+
* 1439 both report exactly 11776 MB free — the fixed reserve a looping
|
|
27920
|
+
* card converges on once it has wrapped. At loop steady state the
|
|
27921
|
+
* number is identical whether the camera recorded yesterday or stopped
|
|
27922
|
+
* a month ago.
|
|
27923
|
+
*/
|
|
27924
|
+
freeMb: number().nullable(),
|
|
27925
|
+
/** True when the camera reports the volume writable (`property` RW). */
|
|
27926
|
+
writable: boolean().optional()
|
|
27927
|
+
});
|
|
27928
|
+
/**
|
|
27929
|
+
* What the camera is doing with its own storage, right now.
|
|
27930
|
+
*
|
|
27931
|
+
* Every scalar is nullable and **null means the camera did not answer**,
|
|
27932
|
+
* never a default. A form that seeds `0` from an unanswered read invites
|
|
27933
|
+
* the operator to save that 0 back onto the camera.
|
|
27934
|
+
*/
|
|
27935
|
+
var RecordingOnboardStatusSchema = object({
|
|
27936
|
+
storage: discriminatedUnion("kind", [
|
|
27937
|
+
object({
|
|
27938
|
+
kind: literal("present"),
|
|
27939
|
+
volumes: array(OnboardStorageVolumeSchema)
|
|
27940
|
+
}),
|
|
27941
|
+
object({
|
|
27942
|
+
kind: literal("absent"),
|
|
27943
|
+
reason: string()
|
|
27944
|
+
}),
|
|
27945
|
+
object({
|
|
27946
|
+
kind: literal("unknown"),
|
|
27947
|
+
reason: string()
|
|
27948
|
+
})
|
|
27949
|
+
]),
|
|
27950
|
+
tracks: array(object({
|
|
27951
|
+
id: string(),
|
|
27952
|
+
enabled: boolean(),
|
|
27953
|
+
isVideo: boolean(),
|
|
27954
|
+
/** From the camera's own track description. Null when it does not say. */
|
|
27955
|
+
codec: string().nullable(),
|
|
27956
|
+
resolution: string().nullable(),
|
|
27957
|
+
/** Per-track overwrite flag, where the firmware keeps it per track. */
|
|
27958
|
+
overwriteWhenFull: boolean().nullable()
|
|
27959
|
+
})),
|
|
27960
|
+
/**
|
|
27961
|
+
* The track the write path targets — the enabled VIDEO one. Null when
|
|
27962
|
+
* no track could be identified, which is itself a refusal reason.
|
|
27963
|
+
*/
|
|
27964
|
+
primaryTrackId: string().nullable(),
|
|
27965
|
+
/** Master "record to the card at all" switch. */
|
|
27966
|
+
enabled: boolean().nullable(),
|
|
27967
|
+
overwriteWhenFull: boolean().nullable(),
|
|
27968
|
+
preRecordSec: number().nullable(),
|
|
27969
|
+
postRecordSec: number().nullable(),
|
|
27970
|
+
/** Length of one recorded file, in minutes. */
|
|
27971
|
+
segmentMinutes: number().nullable(),
|
|
27972
|
+
/** The primary track's weekly windows, flattened. */
|
|
27973
|
+
windows: array(RecordWindowSchema),
|
|
27974
|
+
/**
|
|
27975
|
+
* How many windows the camera described that CamStack could NOT read —
|
|
27976
|
+
* an unrecognised trigger, an unparseable clock, a weekday it does not
|
|
27977
|
+
* name.
|
|
27978
|
+
*
|
|
27979
|
+
* A dropped window is work the reader threw away, and a schedule that
|
|
27980
|
+
* silently shows fewer rows than the camera holds is how an operator
|
|
27981
|
+
* saves back a schedule shorter than the one they were looking at
|
|
27982
|
+
* (D391). Non-zero means the window list is INCOMPLETE and a write
|
|
27983
|
+
* that replaces it would delete what was not shown — which is why a
|
|
27984
|
+
* provider reporting a non-zero count also reports the schedule as not
|
|
27985
|
+
* writable.
|
|
27986
|
+
*/
|
|
27987
|
+
unreadableWindows: number(),
|
|
27988
|
+
/**
|
|
27989
|
+
* The camera is scheduled to record and has NO usable storage.
|
|
27990
|
+
*
|
|
27991
|
+
* A first-class fact because it is the fleet's most common silent
|
|
27992
|
+
* defect: measured 2026-09-22, 1441 and 3831 are both motion-recording
|
|
27993
|
+
* to a card that is not there. Neither the schedule nor the storage
|
|
27994
|
+
* read says anything wrong on its own; only the pair does.
|
|
27995
|
+
*/
|
|
27996
|
+
recordingToNowhere: boolean(),
|
|
27997
|
+
lastFetchedAt: number()
|
|
27998
|
+
});
|
|
27999
|
+
/** Numeric range descriptor — `{ min, max, step }` per the getOptions convention. */
|
|
28000
|
+
var RangeSchema = object({
|
|
28001
|
+
min: number(),
|
|
28002
|
+
max: number(),
|
|
28003
|
+
step: number()
|
|
28004
|
+
});
|
|
28005
|
+
/**
|
|
28006
|
+
* The values a camera actually takes for a numeric field, when they are a SET
|
|
28007
|
+
* rather than a range.
|
|
28008
|
+
*
|
|
28009
|
+
* `{min,max,step}` cannot say what these two firmwares do. Measured on 1436
|
|
28010
|
+
* (I91DN) on 2026-09-22 by writing each value and reading it back:
|
|
28011
|
+
*
|
|
28012
|
+
* - pre-record: `0, 5, 10, 15, 20, 25, 30` and `2147483647` (INT32_MAX, the
|
|
28013
|
+
* camera's "no limit" — `-1` and `4294967295` both land on it);
|
|
28014
|
+
* - post-record: `5, 10, 30, 60, 120, 300, 600`.
|
|
28015
|
+
*
|
|
28016
|
+
* Neither is expressible as a step: the first has a sentinel two billion away
|
|
28017
|
+
* from its neighbours, the second doubles and then jumps. A range that tried
|
|
28018
|
+
* would forbid values the camera takes AND permit values it silently replaces
|
|
28019
|
+
* with 5 — wrong in both directions at once.
|
|
28020
|
+
*
|
|
28021
|
+
* `sentinel` names the member that is not a duration, so a surface can render
|
|
28022
|
+
* "no limit" instead of `2147483647` seconds.
|
|
28023
|
+
*/
|
|
28024
|
+
var AllowedValuesSchema = object({
|
|
28025
|
+
values: array(number()).min(1),
|
|
28026
|
+
sentinel: object({
|
|
28027
|
+
value: number(),
|
|
28028
|
+
meaning: _enum(["no-limit", "disabled"])
|
|
28029
|
+
}).optional()
|
|
28030
|
+
});
|
|
28031
|
+
/**
|
|
28032
|
+
* Per-field availability on ONE camera.
|
|
28033
|
+
*
|
|
28034
|
+
* The field exists on every camera — this says whether this one can be
|
|
28035
|
+
* read and whether it can be written, and `reason` says why not when
|
|
28036
|
+
* either is false. The UI renders the control DISABLED with the reason
|
|
28037
|
+
* rather than hiding it, so a limitation is legible instead of looking
|
|
28038
|
+
* like a missing feature.
|
|
28039
|
+
*/
|
|
28040
|
+
var OnboardFieldSupportSchema = object({
|
|
28041
|
+
readable: boolean(),
|
|
28042
|
+
writable: boolean(),
|
|
28043
|
+
/** Required whenever `readable` or `writable` is false. */
|
|
28044
|
+
reason: string().optional()
|
|
28045
|
+
});
|
|
28046
|
+
/** What this camera's schedule model can express. */
|
|
28047
|
+
var OnboardScheduleSupportSchema = object({
|
|
28048
|
+
support: OnboardFieldSupportSchema,
|
|
28049
|
+
/**
|
|
28050
|
+
* The smallest time step the camera can express, in minutes.
|
|
28051
|
+
*
|
|
28052
|
+
* Hikvision takes arbitrary minutes (`00:05:00`–`23:57:00` observed on
|
|
28053
|
+
* 1436's track 103). Reolink's schedule is a 7×24 HOUR mask, so 60. A
|
|
28054
|
+
* window whose edges are not a multiple of this is REFUSED rather than
|
|
28055
|
+
* quietly rounded — rounding is how an operator's 06:30 becomes 06:00
|
|
28056
|
+
* and nothing says so.
|
|
28057
|
+
*/
|
|
28058
|
+
granularityMinutes: number(),
|
|
28059
|
+
/** Triggers this camera can record on. A window naming another is refused. */
|
|
28060
|
+
triggers: array(RecordTriggerSchema),
|
|
28061
|
+
/**
|
|
28062
|
+
* False when the camera stores ONE trigger per time range, so two
|
|
28063
|
+
* windows overlapping on the same day cannot carry different triggers.
|
|
28064
|
+
* True on Reolink, whose mask is per-trigger and independent.
|
|
28065
|
+
*/
|
|
28066
|
+
supportsOverlappingTriggers: boolean()
|
|
28067
|
+
});
|
|
28068
|
+
var RecordingOnboardOptionsSchema = object({
|
|
28069
|
+
enabled: OnboardFieldSupportSchema,
|
|
28070
|
+
overwriteWhenFull: OnboardFieldSupportSchema,
|
|
28071
|
+
preRecordSec: OnboardFieldSupportSchema,
|
|
28072
|
+
preRecordSecRange: RangeSchema.optional(),
|
|
28073
|
+
/** Preferred over the range when the camera takes a SET, not a span. */
|
|
28074
|
+
preRecordSecAllowed: AllowedValuesSchema.optional(),
|
|
28075
|
+
postRecordSec: OnboardFieldSupportSchema,
|
|
28076
|
+
postRecordSecRange: RangeSchema.optional(),
|
|
28077
|
+
/** Preferred over the range when the camera takes a SET, not a span. */
|
|
28078
|
+
postRecordSecAllowed: AllowedValuesSchema.optional(),
|
|
28079
|
+
segmentMinutes: OnboardFieldSupportSchema,
|
|
28080
|
+
segmentMinutesRange: RangeSchema.optional(),
|
|
28081
|
+
/** Preferred over the range when the camera takes a SET, not a span. */
|
|
28082
|
+
segmentMinutesAllowed: AllowedValuesSchema.optional(),
|
|
28083
|
+
schedule: OnboardScheduleSupportSchema
|
|
28084
|
+
});
|
|
28085
|
+
/**
|
|
28086
|
+
* A partial change. Every field optional.
|
|
28087
|
+
*
|
|
28088
|
+
* Unlike the other `deviceConfig` caps, a provider here does **NOT**
|
|
28089
|
+
* silently ignore a field it cannot support — it refuses, by name,
|
|
28090
|
+
* through {@link describeOnboardRefusal}. Silence on a recording setting
|
|
28091
|
+
* is the failure D62 exists to prevent: the operator believes the camera
|
|
28092
|
+
* is recording the way the form says, and it is not.
|
|
28093
|
+
*/
|
|
28094
|
+
var RecordingOnboardPatchSchema = object({
|
|
28095
|
+
enabled: boolean().optional(),
|
|
28096
|
+
overwriteWhenFull: boolean().optional(),
|
|
28097
|
+
preRecordSec: number().optional(),
|
|
28098
|
+
postRecordSec: number().optional(),
|
|
28099
|
+
segmentMinutes: number().optional(),
|
|
28100
|
+
/** The complete new window set for the primary track — not a delta. */
|
|
28101
|
+
windows: array(RecordWindowSchema).optional()
|
|
28102
|
+
});
|
|
28103
|
+
var recordingOnboardCapability = {
|
|
28104
|
+
name: "recording-onboard",
|
|
28105
|
+
scope: "device",
|
|
28106
|
+
deviceNative: true,
|
|
28107
|
+
mode: "singleton",
|
|
28108
|
+
deviceTypes: [DeviceType.Camera],
|
|
28109
|
+
deviceConfig: { ui: {
|
|
28110
|
+
kind: "derived-form",
|
|
28111
|
+
builderId: "recording-onboard",
|
|
28112
|
+
tab: "recording"
|
|
28113
|
+
} },
|
|
28114
|
+
methods: {
|
|
28115
|
+
getOptions: method(object({ deviceId: number() }), RecordingOnboardOptionsSchema),
|
|
28116
|
+
setSettings: method(object({
|
|
28117
|
+
deviceId: number(),
|
|
28118
|
+
settings: RecordingOnboardPatchSchema
|
|
28119
|
+
}), _void(), {
|
|
28120
|
+
kind: "mutation",
|
|
28121
|
+
auth: "admin"
|
|
28122
|
+
})
|
|
28123
|
+
},
|
|
28124
|
+
status: {
|
|
28125
|
+
schema: RecordingOnboardStatusSchema,
|
|
28126
|
+
kind: "poll"
|
|
28127
|
+
},
|
|
28128
|
+
runtimeState: RecordingOnboardStatusSchema,
|
|
28129
|
+
/**
|
|
28130
|
+
* Runtime-state durability: **restored** — operator-set camera-side
|
|
28131
|
+
* recording config; mutation-driven, and the storage half is the last
|
|
28132
|
+
* thing the camera said about its own card.
|
|
28133
|
+
*
|
|
28134
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
28135
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
28136
|
+
*/
|
|
28137
|
+
durability: "restored",
|
|
28138
|
+
/** Clock fields: written, but excluded from the compare that decides
|
|
28139
|
+
* whether persisting is worth a SQLite commit. */
|
|
28140
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
28141
|
+
};
|
|
28142
|
+
/**
|
|
27000
28143
|
* Generic device-level status snapshot. Auto-registered by `BaseDevice`
|
|
27001
28144
|
* for every device, regardless of provider — the kernel needs a uniform
|
|
27002
28145
|
* cap-keyed slice for the basic device flags every consumer expects to
|
|
@@ -32399,7 +33542,7 @@ method(object({
|
|
|
32399
33542
|
auth: "admin"
|
|
32400
33543
|
}), method(object({ deviceId: number() }), RecordingConfigSchema, {
|
|
32401
33544
|
kind: "query",
|
|
32402
|
-
auth: "
|
|
33545
|
+
auth: "protected"
|
|
32403
33546
|
}), method(object({
|
|
32404
33547
|
deviceId: number(),
|
|
32405
33548
|
profile: string(),
|
|
@@ -32629,13 +33772,101 @@ var ExportStateSchema = _enum([
|
|
|
32629
33772
|
"expired",
|
|
32630
33773
|
"deleted"
|
|
32631
33774
|
]);
|
|
32632
|
-
/**
|
|
33775
|
+
/**
|
|
33776
|
+
* WHAT an export is — the authority, as opposed to the four top-level fields
|
|
33777
|
+
* the Library sorts and labels on (D558 § 2.2).
|
|
33778
|
+
*
|
|
33779
|
+
* Read it through {@link exportSubjectOf}, never off the record directly: the
|
|
33780
|
+
* field is optional for the history rows written before it existed, and that
|
|
33781
|
+
* absence has exactly one interpreter.
|
|
33782
|
+
*/
|
|
33783
|
+
var ExportSubjectSchema = discriminatedUnion("kind", [object({
|
|
33784
|
+
kind: literal("footage"),
|
|
33785
|
+
deviceId: number(),
|
|
33786
|
+
profiles: array(string()).min(1),
|
|
33787
|
+
fromMs: number(),
|
|
33788
|
+
toMs: number()
|
|
33789
|
+
}), object({
|
|
33790
|
+
kind: literal("clip"),
|
|
33791
|
+
deviceId: number(),
|
|
33792
|
+
provider: string().min(1),
|
|
33793
|
+
source: string().min(1),
|
|
33794
|
+
sourceLabel: string().min(1),
|
|
33795
|
+
clipId: string().min(1),
|
|
33796
|
+
/**
|
|
33797
|
+
* WHERE IN THE CATALOG to confirm this clip — the day window the surface was
|
|
33798
|
+
* already listing when the operator picked the segment.
|
|
33799
|
+
*
|
|
33800
|
+
* It is **not** a time range control and it never becomes one: the record's
|
|
33801
|
+
* `fromMs`/`toMs` come from the catalog ROW and from nothing a caller
|
|
33802
|
+
* supplied (D558 § 5.4.3), and a window that does not contain the clip is a
|
|
33803
|
+
* `catalog-miss`, not a silently wider search. It exists because
|
|
33804
|
+
* `videoclips.listClips` takes `since`/`until` and has no by-handle twin:
|
|
33805
|
+
* the catalog check D558 asks for is literally that call, and a call needs a
|
|
33806
|
+
* window. The surface has one — `ClipsBrowser`'s `dayWindow`, one local
|
|
33807
|
+
* wall-clock day, which is also the only width measured to be cheap (one
|
|
33808
|
+
* day on 592 lists 171 clips in 712 ms, a busy day 546 in 2.0 s; twenty days
|
|
33809
|
+
* of one child's events took 3.6–5.4 s).
|
|
33810
|
+
*/
|
|
33811
|
+
catalogWindow: object({
|
|
33812
|
+
sinceMs: number(),
|
|
33813
|
+
untilMs: number()
|
|
33814
|
+
}),
|
|
33815
|
+
profile: _enum([
|
|
33816
|
+
"high",
|
|
33817
|
+
"mid",
|
|
33818
|
+
"low"
|
|
33819
|
+
]),
|
|
33820
|
+
/**
|
|
33821
|
+
* The operator's authorisation to wake a sleeping camera for this export.
|
|
33822
|
+
* ONE definition, in the cap that owns the clip read ({@link ClipWakeSchema}),
|
|
33823
|
+
* because the gate that honours it is the clip provider's sleep gate — a
|
|
33824
|
+
* second enum here would be a second contract. Absent by default; never
|
|
33825
|
+
* settable by a scheduler or a retry.
|
|
33826
|
+
*
|
|
33827
|
+
* **One authorised yes is ONE wake.** A failed clip export is retried only by
|
|
33828
|
+
* an operator act that asks again; a queued job that outlived its wake fails
|
|
33829
|
+
* with a reason rather than waking on its turn; and this subject carries
|
|
33830
|
+
* exactly one profile precisely so one tap is never two fetches (D558 § 5.2).
|
|
33831
|
+
*/
|
|
33832
|
+
wake: ClipWakeSchema.optional()
|
|
33833
|
+
})]);
|
|
33834
|
+
/**
|
|
33835
|
+
* One export job / history row.
|
|
33836
|
+
*
|
|
33837
|
+
* **`subject` is the AUTHORITY on what was exported. `deviceId`, `profile`,
|
|
33838
|
+
* `fromMs` and `toMs` are its PROJECTION** — kept top-level because the whole
|
|
33839
|
+
* Library sorts and labels on them (`library-items.ts` orders an export by
|
|
33840
|
+
* `fromMs`; `export-format.ts` draws `rangeLabel` from the pair), and a row
|
|
33841
|
+
* that did not fill them would sort under the epoch and render a blank range.
|
|
33842
|
+
* Write to the subject and read from the projection and the two will disagree;
|
|
33843
|
+
* the projection is derived at creation and never edited afterwards.
|
|
33844
|
+
*
|
|
33845
|
+
* And they mean DIFFERENT FACTS for the two kinds, which is the part a reader
|
|
33846
|
+
* who knows only the recording export will get wrong:
|
|
33847
|
+
*
|
|
33848
|
+
* | field | `kind:'footage'` | `kind:'clip'` |
|
|
33849
|
+
* | --- | --- | --- |
|
|
33850
|
+
* | `fromMs`/`toMs` | the stretch the operator ASKED for | the camera's own boundaries, always `clip.timeRange`, never anything a caller supplied |
|
|
33851
|
+
* | `profile` | the stream rendered | the twin actually SERVED (`subject.profile` is the one asked for) |
|
|
33852
|
+
*
|
|
33853
|
+
* Same type, different fact — the shape this repo keeps getting wrong (D385's
|
|
33854
|
+
* two authorities, D224's second copy).
|
|
33855
|
+
*/
|
|
32633
33856
|
var ExportRecordSchema = object({
|
|
32634
33857
|
id: string(),
|
|
32635
33858
|
deviceId: number(),
|
|
32636
33859
|
profile: string(),
|
|
32637
33860
|
fromMs: number(),
|
|
32638
33861
|
toMs: number(),
|
|
33862
|
+
/**
|
|
33863
|
+
* What this export IS. Optional ONLY for the rows written before D558: the
|
|
33864
|
+
* store parses every row through this schema on every read, so a required
|
|
33865
|
+
* field would make the export AUDIT — which is the whole reason rows survive
|
|
33866
|
+
* file deletion — unreadable in one release. Absence means `footage`, and
|
|
33867
|
+
* {@link exportSubjectOf} is the one place that says so.
|
|
33868
|
+
*/
|
|
33869
|
+
subject: ExportSubjectSchema.optional(),
|
|
32639
33870
|
options: ExportOptionsSchema,
|
|
32640
33871
|
state: ExportStateSchema,
|
|
32641
33872
|
/** 0–100 while rendering; null otherwise. */
|
|
@@ -32652,6 +33883,18 @@ var ExportRecordSchema = object({
|
|
|
32652
33883
|
/** Failure reason when state is 'failed'; null otherwise. */
|
|
32653
33884
|
error: string().nullable()
|
|
32654
33885
|
});
|
|
33886
|
+
_enum([
|
|
33887
|
+
"catalog-miss",
|
|
33888
|
+
"catalog-unreachable",
|
|
33889
|
+
"no-file-for-window",
|
|
33890
|
+
"clip-in-progress",
|
|
33891
|
+
"unsupported-option",
|
|
33892
|
+
"sleeping",
|
|
33893
|
+
"camera-refused",
|
|
33894
|
+
"fetch-failed",
|
|
33895
|
+
"too-large-to-transfer",
|
|
33896
|
+
"wake-expired"
|
|
33897
|
+
]);
|
|
32655
33898
|
/** Candidate download URLs (LAN first, then operator extra hosts). */
|
|
32656
33899
|
var ExportDownloadSchema = object({
|
|
32657
33900
|
url: string(),
|
|
@@ -32670,16 +33913,50 @@ var ExportBytesSchema = object({
|
|
|
32670
33913
|
name: string(),
|
|
32671
33914
|
bytes: number().int().nonnegative()
|
|
32672
33915
|
});
|
|
33916
|
+
/** Canonical `profiles[]`, falling back to the legacy singular `profile`. */
|
|
33917
|
+
function resolveExportProfiles(input) {
|
|
33918
|
+
if (input.profiles !== void 0 && input.profiles.length > 0) return [...input.profiles];
|
|
33919
|
+
if (typeof input.profile === "string" && input.profile.length > 0) return [input.profile];
|
|
33920
|
+
return [];
|
|
33921
|
+
}
|
|
32673
33922
|
method(object({
|
|
32674
33923
|
deviceId: number(),
|
|
32675
33924
|
/** @deprecated Prefer `profiles`. Kept so timelapse/notifiers keep working. */
|
|
32676
33925
|
profile: string().optional(),
|
|
32677
33926
|
profiles: array(string()).min(1).optional(),
|
|
32678
|
-
|
|
32679
|
-
|
|
33927
|
+
/** Footage only — a clip's boundaries are the camera's. */
|
|
33928
|
+
fromMs: number().optional(),
|
|
33929
|
+
toMs: number().optional(),
|
|
33930
|
+
/** What to export. Absent means the legacy flat footage request. */
|
|
33931
|
+
subject: ExportSubjectSchema.optional(),
|
|
32680
33932
|
options: ExportOptionsSchema
|
|
32681
33933
|
}).superRefine((v, ctx) => {
|
|
32682
|
-
if (
|
|
33934
|
+
if (v.subject?.kind === "clip") {
|
|
33935
|
+
if (v.subject.deviceId !== v.deviceId) ctx.addIssue({
|
|
33936
|
+
code: ZodIssueCode.custom,
|
|
33937
|
+
message: `subject.deviceId (${v.subject.deviceId}) must equal deviceId (${v.deviceId}) — the top-level field is what per-device scope enforcement reads`,
|
|
33938
|
+
path: ["subject", "deviceId"]
|
|
33939
|
+
});
|
|
33940
|
+
if (v.fromMs !== void 0 || v.toMs !== void 0) ctx.addIssue({
|
|
33941
|
+
code: ZodIssueCode.custom,
|
|
33942
|
+
message: "a clip export asks for no time range: the camera chose the boundaries and they are read from the catalog row",
|
|
33943
|
+
path: ["fromMs"]
|
|
33944
|
+
});
|
|
33945
|
+
return;
|
|
33946
|
+
}
|
|
33947
|
+
if (v.subject?.kind === "footage" && v.subject.deviceId !== v.deviceId) ctx.addIssue({
|
|
33948
|
+
code: ZodIssueCode.custom,
|
|
33949
|
+
message: `subject.deviceId (${v.subject.deviceId}) must equal deviceId (${v.deviceId})`,
|
|
33950
|
+
path: ["subject", "deviceId"]
|
|
33951
|
+
});
|
|
33952
|
+
const fromMs = v.subject?.kind === "footage" ? v.subject.fromMs : v.fromMs;
|
|
33953
|
+
const toMs = v.subject?.kind === "footage" ? v.subject.toMs : v.toMs;
|
|
33954
|
+
if (typeof fromMs !== "number" || typeof toMs !== "number") ctx.addIssue({
|
|
33955
|
+
code: ZodIssueCode.custom,
|
|
33956
|
+
message: "a footage export needs fromMs and toMs",
|
|
33957
|
+
path: ["fromMs"]
|
|
33958
|
+
});
|
|
33959
|
+
if ((v.subject?.kind === "footage" ? [...v.subject.profiles] : resolveExportProfiles(v)).length < 1) ctx.addIssue({
|
|
32683
33960
|
code: ZodIssueCode.custom,
|
|
32684
33961
|
message: "pass profiles[] (min 1) or legacy profile",
|
|
32685
33962
|
path: ["profiles"]
|
|
@@ -35491,6 +36768,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
35491
36768
|
pressureSensor: pressureSensorCapability,
|
|
35492
36769
|
privacyMask: privacyMaskCapability,
|
|
35493
36770
|
ptzAutotrack: ptzAutotrackCapability,
|
|
36771
|
+
recordingOnboard: recordingOnboardCapability,
|
|
35494
36772
|
recordingSignal: recordingSignalCapability,
|
|
35495
36773
|
sceneMonitor: sceneMonitorCapability,
|
|
35496
36774
|
scriptRunner: scriptRunnerCapability,
|
|
@@ -36652,7 +37930,1336 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
36652
37930
|
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder;
|
|
36653
37931
|
new Set(Object.values(DeviceType));
|
|
36654
37932
|
DeviceFeature.BatteryOperated;
|
|
37933
|
+
/**
|
|
37934
|
+
* The vocabulary, in the order a picker offers it.
|
|
37935
|
+
*
|
|
37936
|
+
* Adding a key here is not enough to make it pickable: both glyph tables must
|
|
37937
|
+
* gain it too, and their tests fail until they do. That is the intended
|
|
37938
|
+
* friction — it is the only thing that keeps the two surfaces honest.
|
|
37939
|
+
*/
|
|
37940
|
+
var DISPLAY_ICON_VOCABULARY = [
|
|
37941
|
+
{
|
|
37942
|
+
key: "camera",
|
|
37943
|
+
group: "device",
|
|
37944
|
+
synonyms: [
|
|
37945
|
+
"telecamera",
|
|
37946
|
+
"videocamera",
|
|
37947
|
+
"camera",
|
|
37948
|
+
"cam"
|
|
37949
|
+
]
|
|
37950
|
+
},
|
|
37951
|
+
{
|
|
37952
|
+
key: "network",
|
|
37953
|
+
group: "device",
|
|
37954
|
+
synonyms: [
|
|
37955
|
+
"rete",
|
|
37956
|
+
"network",
|
|
37957
|
+
"lan"
|
|
37958
|
+
]
|
|
37959
|
+
},
|
|
37960
|
+
{
|
|
37961
|
+
key: "toggle-left",
|
|
37962
|
+
group: "device",
|
|
37963
|
+
synonyms: [
|
|
37964
|
+
"interruttore",
|
|
37965
|
+
"switch",
|
|
37966
|
+
"toggle"
|
|
37967
|
+
]
|
|
37968
|
+
},
|
|
37969
|
+
{
|
|
37970
|
+
key: "toggle-right",
|
|
37971
|
+
group: "device",
|
|
37972
|
+
synonyms: [
|
|
37973
|
+
"interruttore",
|
|
37974
|
+
"switch",
|
|
37975
|
+
"toggle",
|
|
37976
|
+
"acceso"
|
|
37977
|
+
]
|
|
37978
|
+
},
|
|
37979
|
+
{
|
|
37980
|
+
key: "circle-dot",
|
|
37981
|
+
group: "device",
|
|
37982
|
+
synonyms: [
|
|
37983
|
+
"pulsante",
|
|
37984
|
+
"bottone",
|
|
37985
|
+
"button",
|
|
37986
|
+
"dot"
|
|
37987
|
+
]
|
|
37988
|
+
},
|
|
37989
|
+
{
|
|
37990
|
+
key: "refresh-cw",
|
|
37991
|
+
group: "device",
|
|
37992
|
+
synonyms: [
|
|
37993
|
+
"aggiorna",
|
|
37994
|
+
"ricarica",
|
|
37995
|
+
"refresh",
|
|
37996
|
+
"reload",
|
|
37997
|
+
"ciclo"
|
|
37998
|
+
]
|
|
37999
|
+
},
|
|
38000
|
+
{
|
|
38001
|
+
key: "box",
|
|
38002
|
+
group: "device",
|
|
38003
|
+
synonyms: [
|
|
38004
|
+
"scatola",
|
|
38005
|
+
"box",
|
|
38006
|
+
"contenitore"
|
|
38007
|
+
]
|
|
38008
|
+
},
|
|
38009
|
+
{
|
|
38010
|
+
key: "scroll-text",
|
|
38011
|
+
group: "device",
|
|
38012
|
+
synonyms: [
|
|
38013
|
+
"registro",
|
|
38014
|
+
"log",
|
|
38015
|
+
"testo"
|
|
38016
|
+
]
|
|
38017
|
+
},
|
|
38018
|
+
{
|
|
38019
|
+
key: "workflow",
|
|
38020
|
+
group: "device",
|
|
38021
|
+
synonyms: [
|
|
38022
|
+
"automazione",
|
|
38023
|
+
"flusso",
|
|
38024
|
+
"workflow",
|
|
38025
|
+
"scenario"
|
|
38026
|
+
]
|
|
38027
|
+
},
|
|
38028
|
+
{
|
|
38029
|
+
key: "lock",
|
|
38030
|
+
group: "device",
|
|
38031
|
+
synonyms: [
|
|
38032
|
+
"serratura",
|
|
38033
|
+
"chiave",
|
|
38034
|
+
"lucchetto",
|
|
38035
|
+
"chiuso",
|
|
38036
|
+
"locked"
|
|
38037
|
+
]
|
|
38038
|
+
},
|
|
38039
|
+
{
|
|
38040
|
+
key: "lock-open",
|
|
38041
|
+
group: "device",
|
|
38042
|
+
synonyms: [
|
|
38043
|
+
"serratura",
|
|
38044
|
+
"aperta",
|
|
38045
|
+
"sbloccato",
|
|
38046
|
+
"unlocked"
|
|
38047
|
+
]
|
|
38048
|
+
},
|
|
38049
|
+
{
|
|
38050
|
+
key: "blinds",
|
|
38051
|
+
group: "device",
|
|
38052
|
+
synonyms: [
|
|
38053
|
+
"tapparella",
|
|
38054
|
+
"persiana",
|
|
38055
|
+
"serranda",
|
|
38056
|
+
"avvolgibile",
|
|
38057
|
+
"shutter",
|
|
38058
|
+
"blind",
|
|
38059
|
+
"veneziana"
|
|
38060
|
+
]
|
|
38061
|
+
},
|
|
38062
|
+
{
|
|
38063
|
+
key: "air-vent",
|
|
38064
|
+
group: "device",
|
|
38065
|
+
synonyms: [
|
|
38066
|
+
"bocchetta",
|
|
38067
|
+
"aria",
|
|
38068
|
+
"ventilazione",
|
|
38069
|
+
"condizionatore",
|
|
38070
|
+
"vent"
|
|
38071
|
+
]
|
|
38072
|
+
},
|
|
38073
|
+
{
|
|
38074
|
+
key: "monitor-play",
|
|
38075
|
+
group: "device",
|
|
38076
|
+
synonyms: [
|
|
38077
|
+
"schermo",
|
|
38078
|
+
"riproduzione",
|
|
38079
|
+
"player",
|
|
38080
|
+
"display"
|
|
38081
|
+
]
|
|
38082
|
+
},
|
|
38083
|
+
{
|
|
38084
|
+
key: "sliders-horizontal",
|
|
38085
|
+
group: "device",
|
|
38086
|
+
synonyms: [
|
|
38087
|
+
"regolazione",
|
|
38088
|
+
"cursori",
|
|
38089
|
+
"impostazioni",
|
|
38090
|
+
"slider"
|
|
38091
|
+
]
|
|
38092
|
+
},
|
|
38093
|
+
{
|
|
38094
|
+
key: "map-pin",
|
|
38095
|
+
group: "device",
|
|
38096
|
+
synonyms: [
|
|
38097
|
+
"posizione",
|
|
38098
|
+
"luogo",
|
|
38099
|
+
"mappa",
|
|
38100
|
+
"pin"
|
|
38101
|
+
]
|
|
38102
|
+
},
|
|
38103
|
+
{
|
|
38104
|
+
key: "bot",
|
|
38105
|
+
group: "device",
|
|
38106
|
+
synonyms: [
|
|
38107
|
+
"robot",
|
|
38108
|
+
"aspirapolvere",
|
|
38109
|
+
"bot"
|
|
38110
|
+
]
|
|
38111
|
+
},
|
|
38112
|
+
{
|
|
38113
|
+
key: "tractor",
|
|
38114
|
+
group: "device",
|
|
38115
|
+
synonyms: [
|
|
38116
|
+
"trattore",
|
|
38117
|
+
"tosaerba",
|
|
38118
|
+
"giardino"
|
|
38119
|
+
]
|
|
38120
|
+
},
|
|
38121
|
+
{
|
|
38122
|
+
key: "image",
|
|
38123
|
+
group: "device",
|
|
38124
|
+
synonyms: [
|
|
38125
|
+
"immagine",
|
|
38126
|
+
"foto",
|
|
38127
|
+
"snapshot"
|
|
38128
|
+
]
|
|
38129
|
+
},
|
|
38130
|
+
{
|
|
38131
|
+
key: "bone",
|
|
38132
|
+
group: "device",
|
|
38133
|
+
synonyms: ["osso", "cane"]
|
|
38134
|
+
},
|
|
38135
|
+
{
|
|
38136
|
+
key: "door-closed",
|
|
38137
|
+
group: "device",
|
|
38138
|
+
synonyms: [
|
|
38139
|
+
"porta",
|
|
38140
|
+
"chiusa",
|
|
38141
|
+
"contatto"
|
|
38142
|
+
]
|
|
38143
|
+
},
|
|
38144
|
+
{
|
|
38145
|
+
key: "door-open",
|
|
38146
|
+
group: "device",
|
|
38147
|
+
synonyms: [
|
|
38148
|
+
"porta",
|
|
38149
|
+
"aperta",
|
|
38150
|
+
"contatto",
|
|
38151
|
+
"ingresso",
|
|
38152
|
+
"uscita"
|
|
38153
|
+
]
|
|
38154
|
+
},
|
|
38155
|
+
{
|
|
38156
|
+
key: "crosshair",
|
|
38157
|
+
group: "device",
|
|
38158
|
+
synonyms: [
|
|
38159
|
+
"mirino",
|
|
38160
|
+
"puntamento",
|
|
38161
|
+
"centro"
|
|
38162
|
+
]
|
|
38163
|
+
},
|
|
38164
|
+
{
|
|
38165
|
+
key: "eye",
|
|
38166
|
+
group: "device",
|
|
38167
|
+
synonyms: [
|
|
38168
|
+
"occhio",
|
|
38169
|
+
"visibile",
|
|
38170
|
+
"visto"
|
|
38171
|
+
]
|
|
38172
|
+
},
|
|
38173
|
+
{
|
|
38174
|
+
key: "eye-off",
|
|
38175
|
+
group: "device",
|
|
38176
|
+
synonyms: [
|
|
38177
|
+
"privacy",
|
|
38178
|
+
"nascosto",
|
|
38179
|
+
"oscurato",
|
|
38180
|
+
"mascherato",
|
|
38181
|
+
"invisibile"
|
|
38182
|
+
]
|
|
38183
|
+
},
|
|
38184
|
+
{
|
|
38185
|
+
key: "smartphone",
|
|
38186
|
+
group: "device",
|
|
38187
|
+
synonyms: [
|
|
38188
|
+
"telefono",
|
|
38189
|
+
"cellulare",
|
|
38190
|
+
"smartphone"
|
|
38191
|
+
]
|
|
38192
|
+
},
|
|
38193
|
+
{
|
|
38194
|
+
key: "phone",
|
|
38195
|
+
group: "device",
|
|
38196
|
+
synonyms: ["telefono", "chiamata"]
|
|
38197
|
+
},
|
|
38198
|
+
{
|
|
38199
|
+
key: "tablet",
|
|
38200
|
+
group: "device",
|
|
38201
|
+
synonyms: ["tablet", "ipad"]
|
|
38202
|
+
},
|
|
38203
|
+
{
|
|
38204
|
+
key: "laptop",
|
|
38205
|
+
group: "device",
|
|
38206
|
+
synonyms: [
|
|
38207
|
+
"portatile",
|
|
38208
|
+
"laptop",
|
|
38209
|
+
"notebook"
|
|
38210
|
+
]
|
|
38211
|
+
},
|
|
38212
|
+
{
|
|
38213
|
+
key: "monitor",
|
|
38214
|
+
group: "device",
|
|
38215
|
+
synonyms: ["monitor", "schermo"]
|
|
38216
|
+
},
|
|
38217
|
+
{
|
|
38218
|
+
key: "tv",
|
|
38219
|
+
group: "device",
|
|
38220
|
+
synonyms: ["televisore", "tv"]
|
|
38221
|
+
},
|
|
38222
|
+
{
|
|
38223
|
+
key: "speaker",
|
|
38224
|
+
group: "device",
|
|
38225
|
+
synonyms: [
|
|
38226
|
+
"altoparlante",
|
|
38227
|
+
"cassa",
|
|
38228
|
+
"speaker"
|
|
38229
|
+
]
|
|
38230
|
+
},
|
|
38231
|
+
{
|
|
38232
|
+
key: "printer",
|
|
38233
|
+
group: "device",
|
|
38234
|
+
synonyms: ["stampante"]
|
|
38235
|
+
},
|
|
38236
|
+
{
|
|
38237
|
+
key: "projector",
|
|
38238
|
+
group: "device",
|
|
38239
|
+
synonyms: ["proiettore"]
|
|
38240
|
+
},
|
|
38241
|
+
{
|
|
38242
|
+
key: "gamepad-2",
|
|
38243
|
+
group: "device",
|
|
38244
|
+
synonyms: [
|
|
38245
|
+
"console",
|
|
38246
|
+
"gioco",
|
|
38247
|
+
"joystick"
|
|
38248
|
+
]
|
|
38249
|
+
},
|
|
38250
|
+
{
|
|
38251
|
+
key: "radio",
|
|
38252
|
+
group: "device",
|
|
38253
|
+
synonyms: ["radio"]
|
|
38254
|
+
},
|
|
38255
|
+
{
|
|
38256
|
+
key: "router",
|
|
38257
|
+
group: "device",
|
|
38258
|
+
synonyms: ["router", "modem"]
|
|
38259
|
+
},
|
|
38260
|
+
{
|
|
38261
|
+
key: "bluetooth",
|
|
38262
|
+
group: "device",
|
|
38263
|
+
synonyms: ["bluetooth"]
|
|
38264
|
+
},
|
|
38265
|
+
{
|
|
38266
|
+
key: "cpu",
|
|
38267
|
+
group: "device",
|
|
38268
|
+
synonyms: [
|
|
38269
|
+
"processore",
|
|
38270
|
+
"cpu",
|
|
38271
|
+
"chip",
|
|
38272
|
+
"dispositivo"
|
|
38273
|
+
]
|
|
38274
|
+
},
|
|
38275
|
+
{
|
|
38276
|
+
key: "hard-drive",
|
|
38277
|
+
group: "device",
|
|
38278
|
+
synonyms: [
|
|
38279
|
+
"disco",
|
|
38280
|
+
"hdd",
|
|
38281
|
+
"archiviazione",
|
|
38282
|
+
"storage"
|
|
38283
|
+
]
|
|
38284
|
+
},
|
|
38285
|
+
{
|
|
38286
|
+
key: "server",
|
|
38287
|
+
group: "device",
|
|
38288
|
+
synonyms: ["server", "nas"]
|
|
38289
|
+
},
|
|
38290
|
+
{
|
|
38291
|
+
key: "mic",
|
|
38292
|
+
group: "device",
|
|
38293
|
+
synonyms: ["microfono", "audio"]
|
|
38294
|
+
},
|
|
38295
|
+
{
|
|
38296
|
+
key: "mic-off",
|
|
38297
|
+
group: "device",
|
|
38298
|
+
synonyms: [
|
|
38299
|
+
"microfono",
|
|
38300
|
+
"spento",
|
|
38301
|
+
"muto"
|
|
38302
|
+
]
|
|
38303
|
+
},
|
|
38304
|
+
{
|
|
38305
|
+
key: "video",
|
|
38306
|
+
group: "device",
|
|
38307
|
+
synonyms: ["video"]
|
|
38308
|
+
},
|
|
38309
|
+
{
|
|
38310
|
+
key: "video-off",
|
|
38311
|
+
group: "device",
|
|
38312
|
+
synonyms: ["video", "spento"]
|
|
38313
|
+
},
|
|
38314
|
+
{
|
|
38315
|
+
key: "music",
|
|
38316
|
+
group: "device",
|
|
38317
|
+
synonyms: ["musica"]
|
|
38318
|
+
},
|
|
38319
|
+
{
|
|
38320
|
+
key: "plug",
|
|
38321
|
+
group: "device",
|
|
38322
|
+
synonyms: [
|
|
38323
|
+
"presa",
|
|
38324
|
+
"spina",
|
|
38325
|
+
"plug"
|
|
38326
|
+
]
|
|
38327
|
+
},
|
|
38328
|
+
{
|
|
38329
|
+
key: "plug-zap",
|
|
38330
|
+
group: "device",
|
|
38331
|
+
synonyms: ["presa", "alimentata"]
|
|
38332
|
+
},
|
|
38333
|
+
{
|
|
38334
|
+
key: "power",
|
|
38335
|
+
group: "device",
|
|
38336
|
+
synonyms: [
|
|
38337
|
+
"accensione",
|
|
38338
|
+
"alimentazione",
|
|
38339
|
+
"power"
|
|
38340
|
+
]
|
|
38341
|
+
},
|
|
38342
|
+
{
|
|
38343
|
+
key: "power-off",
|
|
38344
|
+
group: "device",
|
|
38345
|
+
synonyms: ["spegnimento", "spento"]
|
|
38346
|
+
},
|
|
38347
|
+
{
|
|
38348
|
+
key: "cable",
|
|
38349
|
+
group: "device",
|
|
38350
|
+
synonyms: ["cavo"]
|
|
38351
|
+
},
|
|
38352
|
+
{
|
|
38353
|
+
key: "battery",
|
|
38354
|
+
group: "device",
|
|
38355
|
+
synonyms: ["batteria"]
|
|
38356
|
+
},
|
|
38357
|
+
{
|
|
38358
|
+
key: "battery-charging",
|
|
38359
|
+
group: "device",
|
|
38360
|
+
synonyms: [
|
|
38361
|
+
"batteria",
|
|
38362
|
+
"carica",
|
|
38363
|
+
"ricarica"
|
|
38364
|
+
]
|
|
38365
|
+
},
|
|
38366
|
+
{
|
|
38367
|
+
key: "battery-full",
|
|
38368
|
+
group: "device",
|
|
38369
|
+
synonyms: [
|
|
38370
|
+
"batteria",
|
|
38371
|
+
"carica",
|
|
38372
|
+
"piena"
|
|
38373
|
+
]
|
|
38374
|
+
},
|
|
38375
|
+
{
|
|
38376
|
+
key: "battery-low",
|
|
38377
|
+
group: "device",
|
|
38378
|
+
synonyms: ["batteria", "scarica"]
|
|
38379
|
+
},
|
|
38380
|
+
{
|
|
38381
|
+
key: "key",
|
|
38382
|
+
group: "device",
|
|
38383
|
+
synonyms: ["chiave"]
|
|
38384
|
+
},
|
|
38385
|
+
{
|
|
38386
|
+
key: "key-round",
|
|
38387
|
+
group: "device",
|
|
38388
|
+
synonyms: ["chiave", "tonda"]
|
|
38389
|
+
},
|
|
38390
|
+
{
|
|
38391
|
+
key: "mailbox",
|
|
38392
|
+
group: "device",
|
|
38393
|
+
synonyms: [
|
|
38394
|
+
"cassetta",
|
|
38395
|
+
"postale",
|
|
38396
|
+
"posta"
|
|
38397
|
+
]
|
|
38398
|
+
},
|
|
38399
|
+
{
|
|
38400
|
+
key: "package",
|
|
38401
|
+
group: "device",
|
|
38402
|
+
synonyms: ["pacco", "consegna"]
|
|
38403
|
+
},
|
|
38404
|
+
{
|
|
38405
|
+
key: "shield",
|
|
38406
|
+
group: "device",
|
|
38407
|
+
synonyms: [
|
|
38408
|
+
"scudo",
|
|
38409
|
+
"protezione",
|
|
38410
|
+
"sicurezza",
|
|
38411
|
+
"allarme"
|
|
38412
|
+
]
|
|
38413
|
+
},
|
|
38414
|
+
{
|
|
38415
|
+
key: "shield-check",
|
|
38416
|
+
group: "device",
|
|
38417
|
+
synonyms: [
|
|
38418
|
+
"protetto",
|
|
38419
|
+
"sicuro",
|
|
38420
|
+
"armato"
|
|
38421
|
+
]
|
|
38422
|
+
},
|
|
38423
|
+
{
|
|
38424
|
+
key: "shield-off",
|
|
38425
|
+
group: "device",
|
|
38426
|
+
synonyms: [
|
|
38427
|
+
"protezione",
|
|
38428
|
+
"disattivata",
|
|
38429
|
+
"disarmato"
|
|
38430
|
+
]
|
|
38431
|
+
},
|
|
38432
|
+
{
|
|
38433
|
+
key: "briefcase",
|
|
38434
|
+
group: "device",
|
|
38435
|
+
synonyms: [
|
|
38436
|
+
"ufficio",
|
|
38437
|
+
"lavoro",
|
|
38438
|
+
"valigetta",
|
|
38439
|
+
"studio"
|
|
38440
|
+
]
|
|
38441
|
+
},
|
|
38442
|
+
{
|
|
38443
|
+
key: "lightbulb",
|
|
38444
|
+
group: "lighting",
|
|
38445
|
+
synonyms: [
|
|
38446
|
+
"luce",
|
|
38447
|
+
"lampadina",
|
|
38448
|
+
"lampada",
|
|
38449
|
+
"light"
|
|
38450
|
+
]
|
|
38451
|
+
},
|
|
38452
|
+
{
|
|
38453
|
+
key: "lamp",
|
|
38454
|
+
group: "lighting",
|
|
38455
|
+
synonyms: ["lampada", "abatjour"]
|
|
38456
|
+
},
|
|
38457
|
+
{
|
|
38458
|
+
key: "lamp-ceiling",
|
|
38459
|
+
group: "lighting",
|
|
38460
|
+
synonyms: [
|
|
38461
|
+
"plafoniera",
|
|
38462
|
+
"lampadario",
|
|
38463
|
+
"luce",
|
|
38464
|
+
"soffitto"
|
|
38465
|
+
]
|
|
38466
|
+
},
|
|
38467
|
+
{
|
|
38468
|
+
key: "lamp-desk",
|
|
38469
|
+
group: "lighting",
|
|
38470
|
+
synonyms: [
|
|
38471
|
+
"lampada",
|
|
38472
|
+
"scrivania",
|
|
38473
|
+
"abatjour"
|
|
38474
|
+
]
|
|
38475
|
+
},
|
|
38476
|
+
{
|
|
38477
|
+
key: "lamp-floor",
|
|
38478
|
+
group: "lighting",
|
|
38479
|
+
synonyms: [
|
|
38480
|
+
"piantana",
|
|
38481
|
+
"lampada",
|
|
38482
|
+
"terra"
|
|
38483
|
+
]
|
|
38484
|
+
},
|
|
38485
|
+
{
|
|
38486
|
+
key: "flashlight",
|
|
38487
|
+
group: "lighting",
|
|
38488
|
+
synonyms: [
|
|
38489
|
+
"faretto",
|
|
38490
|
+
"torcia",
|
|
38491
|
+
"spot",
|
|
38492
|
+
"faro"
|
|
38493
|
+
]
|
|
38494
|
+
},
|
|
38495
|
+
{
|
|
38496
|
+
key: "heater",
|
|
38497
|
+
group: "lighting",
|
|
38498
|
+
synonyms: [
|
|
38499
|
+
"riscaldamento",
|
|
38500
|
+
"termosifone",
|
|
38501
|
+
"stufa",
|
|
38502
|
+
"calore"
|
|
38503
|
+
]
|
|
38504
|
+
},
|
|
38505
|
+
{
|
|
38506
|
+
key: "snowflake",
|
|
38507
|
+
group: "lighting",
|
|
38508
|
+
synonyms: [
|
|
38509
|
+
"freddo",
|
|
38510
|
+
"raffrescamento",
|
|
38511
|
+
"aria",
|
|
38512
|
+
"condizionata",
|
|
38513
|
+
"neve"
|
|
38514
|
+
]
|
|
38515
|
+
},
|
|
38516
|
+
{
|
|
38517
|
+
key: "thermometer-sun",
|
|
38518
|
+
group: "lighting",
|
|
38519
|
+
synonyms: [
|
|
38520
|
+
"caldo",
|
|
38521
|
+
"temperatura",
|
|
38522
|
+
"alta"
|
|
38523
|
+
]
|
|
38524
|
+
},
|
|
38525
|
+
{
|
|
38526
|
+
key: "thermometer-snowflake",
|
|
38527
|
+
group: "lighting",
|
|
38528
|
+
synonyms: [
|
|
38529
|
+
"freddo",
|
|
38530
|
+
"temperatura",
|
|
38531
|
+
"bassa"
|
|
38532
|
+
]
|
|
38533
|
+
},
|
|
38534
|
+
{
|
|
38535
|
+
key: "refrigerator",
|
|
38536
|
+
group: "lighting",
|
|
38537
|
+
synonyms: ["frigorifero", "frigo"]
|
|
38538
|
+
},
|
|
38539
|
+
{
|
|
38540
|
+
key: "microwave",
|
|
38541
|
+
group: "lighting",
|
|
38542
|
+
synonyms: ["microonde", "forno"]
|
|
38543
|
+
},
|
|
38544
|
+
{
|
|
38545
|
+
key: "washing-machine",
|
|
38546
|
+
group: "lighting",
|
|
38547
|
+
synonyms: [
|
|
38548
|
+
"lavatrice",
|
|
38549
|
+
"lavastoviglie",
|
|
38550
|
+
"asciugatrice"
|
|
38551
|
+
]
|
|
38552
|
+
},
|
|
38553
|
+
{
|
|
38554
|
+
key: "cooking-pot",
|
|
38555
|
+
group: "lighting",
|
|
38556
|
+
synonyms: [
|
|
38557
|
+
"pentola",
|
|
38558
|
+
"cucina",
|
|
38559
|
+
"fornello"
|
|
38560
|
+
]
|
|
38561
|
+
},
|
|
38562
|
+
{
|
|
38563
|
+
key: "utensils",
|
|
38564
|
+
group: "lighting",
|
|
38565
|
+
synonyms: [
|
|
38566
|
+
"cucina",
|
|
38567
|
+
"posate",
|
|
38568
|
+
"sala",
|
|
38569
|
+
"pranzo"
|
|
38570
|
+
]
|
|
38571
|
+
},
|
|
38572
|
+
{
|
|
38573
|
+
key: "thermometer",
|
|
38574
|
+
group: "sensing",
|
|
38575
|
+
synonyms: [
|
|
38576
|
+
"temperatura",
|
|
38577
|
+
"termometro",
|
|
38578
|
+
"termostato"
|
|
38579
|
+
]
|
|
38580
|
+
},
|
|
38581
|
+
{
|
|
38582
|
+
key: "droplets",
|
|
38583
|
+
group: "sensing",
|
|
38584
|
+
synonyms: [
|
|
38585
|
+
"umidita",
|
|
38586
|
+
"acqua",
|
|
38587
|
+
"allagamento",
|
|
38588
|
+
"perdita"
|
|
38589
|
+
]
|
|
38590
|
+
},
|
|
38591
|
+
{
|
|
38592
|
+
key: "droplet",
|
|
38593
|
+
group: "sensing",
|
|
38594
|
+
synonyms: [
|
|
38595
|
+
"goccia",
|
|
38596
|
+
"acqua",
|
|
38597
|
+
"perdita",
|
|
38598
|
+
"allagamento"
|
|
38599
|
+
]
|
|
38600
|
+
},
|
|
38601
|
+
{
|
|
38602
|
+
key: "gauge",
|
|
38603
|
+
group: "sensing",
|
|
38604
|
+
synonyms: [
|
|
38605
|
+
"misura",
|
|
38606
|
+
"livello",
|
|
38607
|
+
"pressione",
|
|
38608
|
+
"indicatore"
|
|
38609
|
+
]
|
|
38610
|
+
},
|
|
38611
|
+
{
|
|
38612
|
+
key: "gauge2",
|
|
38613
|
+
group: "sensing",
|
|
38614
|
+
synonyms: [
|
|
38615
|
+
"misura",
|
|
38616
|
+
"livello",
|
|
38617
|
+
"pressione",
|
|
38618
|
+
"indicatore"
|
|
38619
|
+
],
|
|
38620
|
+
aliasOf: "gauge"
|
|
38621
|
+
},
|
|
38622
|
+
{
|
|
38623
|
+
key: "sun",
|
|
38624
|
+
group: "sensing",
|
|
38625
|
+
synonyms: [
|
|
38626
|
+
"sole",
|
|
38627
|
+
"luminosita",
|
|
38628
|
+
"giorno",
|
|
38629
|
+
"esterno"
|
|
38630
|
+
]
|
|
38631
|
+
},
|
|
38632
|
+
{
|
|
38633
|
+
key: "sun-medium",
|
|
38634
|
+
group: "sensing",
|
|
38635
|
+
synonyms: ["sole", "luminosita"]
|
|
38636
|
+
},
|
|
38637
|
+
{
|
|
38638
|
+
key: "sunrise",
|
|
38639
|
+
group: "sensing",
|
|
38640
|
+
synonyms: ["alba"]
|
|
38641
|
+
},
|
|
38642
|
+
{
|
|
38643
|
+
key: "moon",
|
|
38644
|
+
group: "sensing",
|
|
38645
|
+
synonyms: [
|
|
38646
|
+
"notte",
|
|
38647
|
+
"luna",
|
|
38648
|
+
"notturna",
|
|
38649
|
+
"nightvision"
|
|
38650
|
+
]
|
|
38651
|
+
},
|
|
38652
|
+
{
|
|
38653
|
+
key: "wind",
|
|
38654
|
+
group: "sensing",
|
|
38655
|
+
synonyms: [
|
|
38656
|
+
"vento",
|
|
38657
|
+
"aria",
|
|
38658
|
+
"gas",
|
|
38659
|
+
"monossido",
|
|
38660
|
+
"co"
|
|
38661
|
+
]
|
|
38662
|
+
},
|
|
38663
|
+
{
|
|
38664
|
+
key: "cloud",
|
|
38665
|
+
group: "sensing",
|
|
38666
|
+
synonyms: ["nuvola", "nuvoloso"]
|
|
38667
|
+
},
|
|
38668
|
+
{
|
|
38669
|
+
key: "cloud-rain",
|
|
38670
|
+
group: "sensing",
|
|
38671
|
+
synonyms: ["pioggia"]
|
|
38672
|
+
},
|
|
38673
|
+
{
|
|
38674
|
+
key: "cloud-sun",
|
|
38675
|
+
group: "sensing",
|
|
38676
|
+
synonyms: [
|
|
38677
|
+
"variabile",
|
|
38678
|
+
"sole",
|
|
38679
|
+
"nuvole"
|
|
38680
|
+
]
|
|
38681
|
+
},
|
|
38682
|
+
{
|
|
38683
|
+
key: "waves",
|
|
38684
|
+
group: "sensing",
|
|
38685
|
+
synonyms: [
|
|
38686
|
+
"onde",
|
|
38687
|
+
"acqua",
|
|
38688
|
+
"vibrazione"
|
|
38689
|
+
]
|
|
38690
|
+
},
|
|
38691
|
+
{
|
|
38692
|
+
key: "sprout",
|
|
38693
|
+
group: "sensing",
|
|
38694
|
+
synonyms: [
|
|
38695
|
+
"irrigazione",
|
|
38696
|
+
"pianta",
|
|
38697
|
+
"germoglio",
|
|
38698
|
+
"orto"
|
|
38699
|
+
]
|
|
38700
|
+
},
|
|
38701
|
+
{
|
|
38702
|
+
key: "leaf",
|
|
38703
|
+
group: "sensing",
|
|
38704
|
+
synonyms: [
|
|
38705
|
+
"foglia",
|
|
38706
|
+
"pianta",
|
|
38707
|
+
"verde"
|
|
38708
|
+
]
|
|
38709
|
+
},
|
|
38710
|
+
{
|
|
38711
|
+
key: "flower",
|
|
38712
|
+
group: "sensing",
|
|
38713
|
+
synonyms: ["fiore", "pianta"]
|
|
38714
|
+
},
|
|
38715
|
+
{
|
|
38716
|
+
key: "zap",
|
|
38717
|
+
group: "sensing",
|
|
38718
|
+
synonyms: [
|
|
38719
|
+
"energia",
|
|
38720
|
+
"corrente",
|
|
38721
|
+
"consumo",
|
|
38722
|
+
"watt",
|
|
38723
|
+
"elettricita"
|
|
38724
|
+
]
|
|
38725
|
+
},
|
|
38726
|
+
{
|
|
38727
|
+
key: "flame",
|
|
38728
|
+
group: "sensing",
|
|
38729
|
+
synonyms: [
|
|
38730
|
+
"fiamma",
|
|
38731
|
+
"gas",
|
|
38732
|
+
"fuoco",
|
|
38733
|
+
"incendio"
|
|
38734
|
+
]
|
|
38735
|
+
},
|
|
38736
|
+
{
|
|
38737
|
+
key: "bell",
|
|
38738
|
+
group: "sensing",
|
|
38739
|
+
synonyms: [
|
|
38740
|
+
"campanello",
|
|
38741
|
+
"suoneria",
|
|
38742
|
+
"notifica",
|
|
38743
|
+
"bell",
|
|
38744
|
+
"chime"
|
|
38745
|
+
]
|
|
38746
|
+
},
|
|
38747
|
+
{
|
|
38748
|
+
key: "bell-ring",
|
|
38749
|
+
group: "sensing",
|
|
38750
|
+
synonyms: [
|
|
38751
|
+
"campanello",
|
|
38752
|
+
"suona",
|
|
38753
|
+
"doorbell",
|
|
38754
|
+
"notifica"
|
|
38755
|
+
]
|
|
38756
|
+
},
|
|
38757
|
+
{
|
|
38758
|
+
key: "bell-off",
|
|
38759
|
+
group: "sensing",
|
|
38760
|
+
synonyms: [
|
|
38761
|
+
"silenzioso",
|
|
38762
|
+
"notifiche",
|
|
38763
|
+
"disattivate",
|
|
38764
|
+
"muto"
|
|
38765
|
+
]
|
|
38766
|
+
},
|
|
38767
|
+
{
|
|
38768
|
+
key: "siren",
|
|
38769
|
+
group: "sensing",
|
|
38770
|
+
synonyms: ["sirena", "allarme"]
|
|
38771
|
+
},
|
|
38772
|
+
{
|
|
38773
|
+
key: "radar",
|
|
38774
|
+
group: "sensing",
|
|
38775
|
+
synonyms: [
|
|
38776
|
+
"movimento",
|
|
38777
|
+
"presenza",
|
|
38778
|
+
"pir",
|
|
38779
|
+
"rilevamento",
|
|
38780
|
+
"radar"
|
|
38781
|
+
]
|
|
38782
|
+
},
|
|
38783
|
+
{
|
|
38784
|
+
key: "activity",
|
|
38785
|
+
group: "sensing",
|
|
38786
|
+
synonyms: [
|
|
38787
|
+
"attivita",
|
|
38788
|
+
"sensore",
|
|
38789
|
+
"generico"
|
|
38790
|
+
]
|
|
38791
|
+
},
|
|
38792
|
+
{
|
|
38793
|
+
key: "hash",
|
|
38794
|
+
group: "sensing",
|
|
38795
|
+
synonyms: [
|
|
38796
|
+
"numero",
|
|
38797
|
+
"contatore",
|
|
38798
|
+
"valore"
|
|
38799
|
+
]
|
|
38800
|
+
},
|
|
38801
|
+
{
|
|
38802
|
+
key: "clock",
|
|
38803
|
+
group: "sensing",
|
|
38804
|
+
synonyms: [
|
|
38805
|
+
"orologio",
|
|
38806
|
+
"ora",
|
|
38807
|
+
"tempo"
|
|
38808
|
+
]
|
|
38809
|
+
},
|
|
38810
|
+
{
|
|
38811
|
+
key: "timer",
|
|
38812
|
+
group: "sensing",
|
|
38813
|
+
synonyms: [
|
|
38814
|
+
"timer",
|
|
38815
|
+
"conto",
|
|
38816
|
+
"rovescia"
|
|
38817
|
+
]
|
|
38818
|
+
},
|
|
38819
|
+
{
|
|
38820
|
+
key: "calendar",
|
|
38821
|
+
group: "sensing",
|
|
38822
|
+
synonyms: [
|
|
38823
|
+
"calendario",
|
|
38824
|
+
"data",
|
|
38825
|
+
"pianificazione"
|
|
38826
|
+
]
|
|
38827
|
+
},
|
|
38828
|
+
{
|
|
38829
|
+
key: "pipette",
|
|
38830
|
+
group: "sensing",
|
|
38831
|
+
synonyms: [
|
|
38832
|
+
"qualita",
|
|
38833
|
+
"aria",
|
|
38834
|
+
"misura",
|
|
38835
|
+
"campione"
|
|
38836
|
+
]
|
|
38837
|
+
},
|
|
38838
|
+
{
|
|
38839
|
+
key: "fan",
|
|
38840
|
+
group: "sensing",
|
|
38841
|
+
synonyms: [
|
|
38842
|
+
"ventilatore",
|
|
38843
|
+
"ventola",
|
|
38844
|
+
"aria"
|
|
38845
|
+
]
|
|
38846
|
+
},
|
|
38847
|
+
{
|
|
38848
|
+
key: "bath",
|
|
38849
|
+
group: "sensing",
|
|
38850
|
+
synonyms: [
|
|
38851
|
+
"bagno",
|
|
38852
|
+
"vasca",
|
|
38853
|
+
"doccia"
|
|
38854
|
+
]
|
|
38855
|
+
},
|
|
38856
|
+
{
|
|
38857
|
+
key: "footprints",
|
|
38858
|
+
group: "sensing",
|
|
38859
|
+
synonyms: [
|
|
38860
|
+
"movimento",
|
|
38861
|
+
"passi",
|
|
38862
|
+
"presenza",
|
|
38863
|
+
"motion"
|
|
38864
|
+
]
|
|
38865
|
+
},
|
|
38866
|
+
{
|
|
38867
|
+
key: "alarm-smoke",
|
|
38868
|
+
group: "sensing",
|
|
38869
|
+
synonyms: [
|
|
38870
|
+
"fumo",
|
|
38871
|
+
"antincendio",
|
|
38872
|
+
"rilevatore"
|
|
38873
|
+
]
|
|
38874
|
+
},
|
|
38875
|
+
{
|
|
38876
|
+
key: "shield-alert",
|
|
38877
|
+
group: "sensing",
|
|
38878
|
+
synonyms: [
|
|
38879
|
+
"manomissione",
|
|
38880
|
+
"allarme",
|
|
38881
|
+
"tamper",
|
|
38882
|
+
"avviso"
|
|
38883
|
+
]
|
|
38884
|
+
},
|
|
38885
|
+
{
|
|
38886
|
+
key: "vibrate",
|
|
38887
|
+
group: "sensing",
|
|
38888
|
+
synonyms: [
|
|
38889
|
+
"vibrazione",
|
|
38890
|
+
"urto",
|
|
38891
|
+
"tamper"
|
|
38892
|
+
]
|
|
38893
|
+
},
|
|
38894
|
+
{
|
|
38895
|
+
key: "wifi",
|
|
38896
|
+
group: "sensing",
|
|
38897
|
+
synonyms: [
|
|
38898
|
+
"wifi",
|
|
38899
|
+
"rete",
|
|
38900
|
+
"segnale"
|
|
38901
|
+
]
|
|
38902
|
+
},
|
|
38903
|
+
{
|
|
38904
|
+
key: "wifi-off",
|
|
38905
|
+
group: "sensing",
|
|
38906
|
+
synonyms: [
|
|
38907
|
+
"wifi",
|
|
38908
|
+
"assente",
|
|
38909
|
+
"offline",
|
|
38910
|
+
"disconnesso"
|
|
38911
|
+
]
|
|
38912
|
+
},
|
|
38913
|
+
{
|
|
38914
|
+
key: "volume-2",
|
|
38915
|
+
group: "sensing",
|
|
38916
|
+
synonyms: [
|
|
38917
|
+
"volume",
|
|
38918
|
+
"audio",
|
|
38919
|
+
"altoparlante",
|
|
38920
|
+
"suono"
|
|
38921
|
+
]
|
|
38922
|
+
},
|
|
38923
|
+
{
|
|
38924
|
+
key: "volume-x",
|
|
38925
|
+
group: "sensing",
|
|
38926
|
+
synonyms: [
|
|
38927
|
+
"muto",
|
|
38928
|
+
"silenziato",
|
|
38929
|
+
"volume",
|
|
38930
|
+
"spento"
|
|
38931
|
+
]
|
|
38932
|
+
},
|
|
38933
|
+
{
|
|
38934
|
+
key: "heart",
|
|
38935
|
+
group: "sensing",
|
|
38936
|
+
synonyms: [
|
|
38937
|
+
"cuore",
|
|
38938
|
+
"preferito",
|
|
38939
|
+
"salute"
|
|
38940
|
+
]
|
|
38941
|
+
},
|
|
38942
|
+
{
|
|
38943
|
+
key: "heart-pulse",
|
|
38944
|
+
group: "sensing",
|
|
38945
|
+
synonyms: [
|
|
38946
|
+
"battito",
|
|
38947
|
+
"salute",
|
|
38948
|
+
"monitoraggio"
|
|
38949
|
+
]
|
|
38950
|
+
},
|
|
38951
|
+
{
|
|
38952
|
+
key: "star",
|
|
38953
|
+
group: "sensing",
|
|
38954
|
+
synonyms: [
|
|
38955
|
+
"preferito",
|
|
38956
|
+
"stella",
|
|
38957
|
+
"importante"
|
|
38958
|
+
]
|
|
38959
|
+
},
|
|
38960
|
+
{
|
|
38961
|
+
key: "sparkles",
|
|
38962
|
+
group: "sensing",
|
|
38963
|
+
synonyms: [
|
|
38964
|
+
"automatico",
|
|
38965
|
+
"intelligente",
|
|
38966
|
+
"ai",
|
|
38967
|
+
"scena"
|
|
38968
|
+
]
|
|
38969
|
+
},
|
|
38970
|
+
{
|
|
38971
|
+
key: "house",
|
|
38972
|
+
group: "place",
|
|
38973
|
+
synonyms: [
|
|
38974
|
+
"casa",
|
|
38975
|
+
"abitazione",
|
|
38976
|
+
"home"
|
|
38977
|
+
]
|
|
38978
|
+
},
|
|
38979
|
+
{
|
|
38980
|
+
key: "sofa",
|
|
38981
|
+
group: "place",
|
|
38982
|
+
synonyms: [
|
|
38983
|
+
"salone",
|
|
38984
|
+
"soggiorno",
|
|
38985
|
+
"divano",
|
|
38986
|
+
"living"
|
|
38987
|
+
]
|
|
38988
|
+
},
|
|
38989
|
+
{
|
|
38990
|
+
key: "bed-double",
|
|
38991
|
+
group: "place",
|
|
38992
|
+
synonyms: [
|
|
38993
|
+
"camera",
|
|
38994
|
+
"letto",
|
|
38995
|
+
"matrimoniale"
|
|
38996
|
+
]
|
|
38997
|
+
},
|
|
38998
|
+
{
|
|
38999
|
+
key: "bed",
|
|
39000
|
+
group: "place",
|
|
39001
|
+
synonyms: [
|
|
39002
|
+
"cameretta",
|
|
39003
|
+
"letto",
|
|
39004
|
+
"singolo"
|
|
39005
|
+
]
|
|
39006
|
+
},
|
|
39007
|
+
{
|
|
39008
|
+
key: "warehouse",
|
|
39009
|
+
group: "place",
|
|
39010
|
+
synonyms: [
|
|
39011
|
+
"magazzino",
|
|
39012
|
+
"capanno",
|
|
39013
|
+
"deposito",
|
|
39014
|
+
"cantina"
|
|
39015
|
+
]
|
|
39016
|
+
},
|
|
39017
|
+
{
|
|
39018
|
+
key: "trees",
|
|
39019
|
+
group: "place",
|
|
39020
|
+
synonyms: [
|
|
39021
|
+
"giardino",
|
|
39022
|
+
"alberi",
|
|
39023
|
+
"esterno",
|
|
39024
|
+
"parco"
|
|
39025
|
+
]
|
|
39026
|
+
},
|
|
39027
|
+
{
|
|
39028
|
+
key: "tree-pine",
|
|
39029
|
+
group: "place",
|
|
39030
|
+
synonyms: [
|
|
39031
|
+
"albero",
|
|
39032
|
+
"pino",
|
|
39033
|
+
"giardino"
|
|
39034
|
+
]
|
|
39035
|
+
},
|
|
39036
|
+
{
|
|
39037
|
+
key: "fence",
|
|
39038
|
+
group: "place",
|
|
39039
|
+
synonyms: [
|
|
39040
|
+
"recinto",
|
|
39041
|
+
"cancello",
|
|
39042
|
+
"staccionata",
|
|
39043
|
+
"perimetro"
|
|
39044
|
+
]
|
|
39045
|
+
},
|
|
39046
|
+
{
|
|
39047
|
+
key: "store",
|
|
39048
|
+
group: "place",
|
|
39049
|
+
synonyms: [
|
|
39050
|
+
"negozio",
|
|
39051
|
+
"ingresso",
|
|
39052
|
+
"vetrina"
|
|
39053
|
+
]
|
|
39054
|
+
},
|
|
39055
|
+
{
|
|
39056
|
+
key: "building",
|
|
39057
|
+
group: "place",
|
|
39058
|
+
synonyms: ["edificio", "palazzo"]
|
|
39059
|
+
},
|
|
39060
|
+
{
|
|
39061
|
+
key: "building-2",
|
|
39062
|
+
group: "place",
|
|
39063
|
+
synonyms: [
|
|
39064
|
+
"edificio",
|
|
39065
|
+
"uffici",
|
|
39066
|
+
"condominio"
|
|
39067
|
+
]
|
|
39068
|
+
},
|
|
39069
|
+
{
|
|
39070
|
+
key: "mountain",
|
|
39071
|
+
group: "place",
|
|
39072
|
+
synonyms: [
|
|
39073
|
+
"montagna",
|
|
39074
|
+
"esterno",
|
|
39075
|
+
"panorama"
|
|
39076
|
+
]
|
|
39077
|
+
},
|
|
39078
|
+
{
|
|
39079
|
+
key: "umbrella",
|
|
39080
|
+
group: "place",
|
|
39081
|
+
synonyms: [
|
|
39082
|
+
"tenda",
|
|
39083
|
+
"markise",
|
|
39084
|
+
"ombrellone",
|
|
39085
|
+
"pergola",
|
|
39086
|
+
"veranda"
|
|
39087
|
+
]
|
|
39088
|
+
},
|
|
39089
|
+
{
|
|
39090
|
+
key: "dumbbell",
|
|
39091
|
+
group: "place",
|
|
39092
|
+
synonyms: ["palestra", "attrezzi"]
|
|
39093
|
+
},
|
|
39094
|
+
{
|
|
39095
|
+
key: "wrench",
|
|
39096
|
+
group: "place",
|
|
39097
|
+
synonyms: [
|
|
39098
|
+
"officina",
|
|
39099
|
+
"manutenzione",
|
|
39100
|
+
"attrezzi",
|
|
39101
|
+
"utenze"
|
|
39102
|
+
]
|
|
39103
|
+
},
|
|
39104
|
+
{
|
|
39105
|
+
key: "hammer",
|
|
39106
|
+
group: "place",
|
|
39107
|
+
synonyms: [
|
|
39108
|
+
"officina",
|
|
39109
|
+
"martello",
|
|
39110
|
+
"lavori"
|
|
39111
|
+
]
|
|
39112
|
+
},
|
|
39113
|
+
{
|
|
39114
|
+
key: "drill",
|
|
39115
|
+
group: "place",
|
|
39116
|
+
synonyms: [
|
|
39117
|
+
"officina",
|
|
39118
|
+
"trapano",
|
|
39119
|
+
"lavori"
|
|
39120
|
+
]
|
|
39121
|
+
},
|
|
39122
|
+
{
|
|
39123
|
+
key: "waves-ladder",
|
|
39124
|
+
group: "place",
|
|
39125
|
+
synonyms: ["piscina", "vasca"]
|
|
39126
|
+
},
|
|
39127
|
+
{
|
|
39128
|
+
key: "circle-parking",
|
|
39129
|
+
group: "place",
|
|
39130
|
+
synonyms: [
|
|
39131
|
+
"parcheggio",
|
|
39132
|
+
"posto",
|
|
39133
|
+
"auto",
|
|
39134
|
+
"garage"
|
|
39135
|
+
]
|
|
39136
|
+
},
|
|
39137
|
+
{
|
|
39138
|
+
key: "route",
|
|
39139
|
+
group: "place",
|
|
39140
|
+
synonyms: [
|
|
39141
|
+
"percorso",
|
|
39142
|
+
"strada",
|
|
39143
|
+
"vialetto",
|
|
39144
|
+
"tragitto"
|
|
39145
|
+
]
|
|
39146
|
+
},
|
|
39147
|
+
{
|
|
39148
|
+
key: "car",
|
|
39149
|
+
group: "life",
|
|
39150
|
+
synonyms: [
|
|
39151
|
+
"auto",
|
|
39152
|
+
"macchina",
|
|
39153
|
+
"veicolo",
|
|
39154
|
+
"parcheggio"
|
|
39155
|
+
]
|
|
39156
|
+
},
|
|
39157
|
+
{
|
|
39158
|
+
key: "bike",
|
|
39159
|
+
group: "life",
|
|
39160
|
+
synonyms: [
|
|
39161
|
+
"bicicletta",
|
|
39162
|
+
"bici",
|
|
39163
|
+
"moto"
|
|
39164
|
+
]
|
|
39165
|
+
},
|
|
39166
|
+
{
|
|
39167
|
+
key: "bus",
|
|
39168
|
+
group: "life",
|
|
39169
|
+
synonyms: ["autobus", "pullman"]
|
|
39170
|
+
},
|
|
39171
|
+
{
|
|
39172
|
+
key: "truck",
|
|
39173
|
+
group: "life",
|
|
39174
|
+
synonyms: [
|
|
39175
|
+
"camion",
|
|
39176
|
+
"furgone",
|
|
39177
|
+
"consegna"
|
|
39178
|
+
]
|
|
39179
|
+
},
|
|
39180
|
+
{
|
|
39181
|
+
key: "plane",
|
|
39182
|
+
group: "life",
|
|
39183
|
+
synonyms: ["aereo"]
|
|
39184
|
+
},
|
|
39185
|
+
{
|
|
39186
|
+
key: "train-front",
|
|
39187
|
+
group: "life",
|
|
39188
|
+
synonyms: ["treno"]
|
|
39189
|
+
},
|
|
39190
|
+
{
|
|
39191
|
+
key: "sailboat",
|
|
39192
|
+
group: "life",
|
|
39193
|
+
synonyms: ["barca", "imbarcazione"]
|
|
39194
|
+
},
|
|
39195
|
+
{
|
|
39196
|
+
key: "dog",
|
|
39197
|
+
group: "life",
|
|
39198
|
+
synonyms: ["cane", "animale"]
|
|
39199
|
+
},
|
|
39200
|
+
{
|
|
39201
|
+
key: "cat",
|
|
39202
|
+
group: "life",
|
|
39203
|
+
synonyms: ["gatto", "animale"]
|
|
39204
|
+
},
|
|
39205
|
+
{
|
|
39206
|
+
key: "bird",
|
|
39207
|
+
group: "life",
|
|
39208
|
+
synonyms: ["uccello", "animale"]
|
|
39209
|
+
},
|
|
39210
|
+
{
|
|
39211
|
+
key: "paw-print",
|
|
39212
|
+
group: "life",
|
|
39213
|
+
synonyms: [
|
|
39214
|
+
"animale",
|
|
39215
|
+
"zampa",
|
|
39216
|
+
"pet"
|
|
39217
|
+
]
|
|
39218
|
+
},
|
|
39219
|
+
{
|
|
39220
|
+
key: "baby",
|
|
39221
|
+
group: "life",
|
|
39222
|
+
synonyms: [
|
|
39223
|
+
"neonato",
|
|
39224
|
+
"bimbo",
|
|
39225
|
+
"cameretta",
|
|
39226
|
+
"babymonitor"
|
|
39227
|
+
]
|
|
39228
|
+
},
|
|
39229
|
+
{
|
|
39230
|
+
key: "user",
|
|
39231
|
+
group: "life",
|
|
39232
|
+
synonyms: ["persona", "utente"]
|
|
39233
|
+
},
|
|
39234
|
+
{
|
|
39235
|
+
key: "users",
|
|
39236
|
+
group: "life",
|
|
39237
|
+
synonyms: [
|
|
39238
|
+
"persone",
|
|
39239
|
+
"gruppo",
|
|
39240
|
+
"famiglia"
|
|
39241
|
+
]
|
|
39242
|
+
},
|
|
39243
|
+
{
|
|
39244
|
+
key: "person-standing",
|
|
39245
|
+
group: "life",
|
|
39246
|
+
synonyms: [
|
|
39247
|
+
"persona",
|
|
39248
|
+
"piedi",
|
|
39249
|
+
"presenza"
|
|
39250
|
+
]
|
|
39251
|
+
}
|
|
39252
|
+
];
|
|
39253
|
+
DISPLAY_ICON_VOCABULARY.map((e) => e.key);
|
|
39254
|
+
DISPLAY_ICON_VOCABULARY.filter((e) => e.aliasOf === void 0).map((e) => e.key);
|
|
39255
|
+
new Map(DISPLAY_ICON_VOCABULARY.map((e) => [e.key, e]));
|
|
36655
39256
|
Object.freeze({
|
|
39257
|
+
"accessories.getStatus": {
|
|
39258
|
+
capName: "accessories",
|
|
39259
|
+
capScope: "device",
|
|
39260
|
+
addonId: null,
|
|
39261
|
+
access: "view"
|
|
39262
|
+
},
|
|
36656
39263
|
"accessories.setChildHidden": {
|
|
36657
39264
|
capName: "accessories",
|
|
36658
39265
|
capScope: "device",
|
|
@@ -36935,6 +39542,12 @@ Object.freeze({
|
|
|
36935
39542
|
addonId: null,
|
|
36936
39543
|
access: "view"
|
|
36937
39544
|
},
|
|
39545
|
+
"airQualitySensor.getStatus": {
|
|
39546
|
+
capName: "air-quality-sensor",
|
|
39547
|
+
capScope: "device",
|
|
39548
|
+
addonId: null,
|
|
39549
|
+
access: "view"
|
|
39550
|
+
},
|
|
36938
39551
|
"alarmPanel.arm": {
|
|
36939
39552
|
capName: "alarm-panel",
|
|
36940
39553
|
capScope: "device",
|
|
@@ -36947,6 +39560,12 @@ Object.freeze({
|
|
|
36947
39560
|
addonId: null,
|
|
36948
39561
|
access: "create"
|
|
36949
39562
|
},
|
|
39563
|
+
"alarmPanel.getStatus": {
|
|
39564
|
+
capName: "alarm-panel",
|
|
39565
|
+
capScope: "device",
|
|
39566
|
+
addonId: null,
|
|
39567
|
+
access: "view"
|
|
39568
|
+
},
|
|
36950
39569
|
"alarmPanel.trigger": {
|
|
36951
39570
|
capName: "alarm-panel",
|
|
36952
39571
|
capScope: "device",
|
|
@@ -36995,6 +39614,30 @@ Object.freeze({
|
|
|
36995
39614
|
addonId: null,
|
|
36996
39615
|
access: "create"
|
|
36997
39616
|
},
|
|
39617
|
+
"ambientLightSensor.getStatus": {
|
|
39618
|
+
capName: "ambient-light-sensor",
|
|
39619
|
+
capScope: "device",
|
|
39620
|
+
addonId: null,
|
|
39621
|
+
access: "view"
|
|
39622
|
+
},
|
|
39623
|
+
"audioAnalysis.applyDeviceSettingsPatch": {
|
|
39624
|
+
capName: "audio-analysis",
|
|
39625
|
+
capScope: "device",
|
|
39626
|
+
addonId: null,
|
|
39627
|
+
access: "create"
|
|
39628
|
+
},
|
|
39629
|
+
"audioAnalysis.getDeviceLiveContribution": {
|
|
39630
|
+
capName: "audio-analysis",
|
|
39631
|
+
capScope: "device",
|
|
39632
|
+
addonId: null,
|
|
39633
|
+
access: "view"
|
|
39634
|
+
},
|
|
39635
|
+
"audioAnalysis.getDeviceSettingsContribution": {
|
|
39636
|
+
capName: "audio-analysis",
|
|
39637
|
+
capScope: "device",
|
|
39638
|
+
addonId: null,
|
|
39639
|
+
access: "view"
|
|
39640
|
+
},
|
|
36998
39641
|
"audioAnalysis.resolveDeviceSettings": {
|
|
36999
39642
|
capName: "audio-analysis",
|
|
37000
39643
|
capScope: "device",
|
|
@@ -37157,6 +39800,12 @@ Object.freeze({
|
|
|
37157
39800
|
addonId: null,
|
|
37158
39801
|
access: "create"
|
|
37159
39802
|
},
|
|
39803
|
+
"automationControl.getStatus": {
|
|
39804
|
+
capName: "automation-control",
|
|
39805
|
+
capScope: "device",
|
|
39806
|
+
addonId: null,
|
|
39807
|
+
access: "view"
|
|
39808
|
+
},
|
|
37160
39809
|
"automationControl.trigger": {
|
|
37161
39810
|
capName: "automation-control",
|
|
37162
39811
|
capScope: "device",
|
|
@@ -37253,12 +39902,30 @@ Object.freeze({
|
|
|
37253
39902
|
addonId: null,
|
|
37254
39903
|
access: "create"
|
|
37255
39904
|
},
|
|
39905
|
+
"battery.getStatus": {
|
|
39906
|
+
capName: "battery",
|
|
39907
|
+
capScope: "device",
|
|
39908
|
+
addonId: null,
|
|
39909
|
+
access: "view"
|
|
39910
|
+
},
|
|
37256
39911
|
"battery.wakeForStream": {
|
|
37257
39912
|
capName: "battery",
|
|
37258
39913
|
capScope: "device",
|
|
37259
39914
|
addonId: null,
|
|
37260
39915
|
access: "create"
|
|
37261
39916
|
},
|
|
39917
|
+
"binary.getStatus": {
|
|
39918
|
+
capName: "binary",
|
|
39919
|
+
capScope: "device",
|
|
39920
|
+
addonId: null,
|
|
39921
|
+
access: "view"
|
|
39922
|
+
},
|
|
39923
|
+
"brightness.getStatus": {
|
|
39924
|
+
capName: "brightness",
|
|
39925
|
+
capScope: "device",
|
|
39926
|
+
addonId: null,
|
|
39927
|
+
access: "view"
|
|
39928
|
+
},
|
|
37262
39929
|
"brightness.setBrightness": {
|
|
37263
39930
|
capName: "brightness",
|
|
37264
39931
|
capScope: "device",
|
|
@@ -37373,6 +40040,30 @@ Object.freeze({
|
|
|
37373
40040
|
addonId: null,
|
|
37374
40041
|
access: "view"
|
|
37375
40042
|
},
|
|
40043
|
+
"cameraCredentials.getStatus": {
|
|
40044
|
+
capName: "camera-credentials",
|
|
40045
|
+
capScope: "device",
|
|
40046
|
+
addonId: null,
|
|
40047
|
+
access: "view"
|
|
40048
|
+
},
|
|
40049
|
+
"cameraGridLayout.applyDeviceSettingsPatch": {
|
|
40050
|
+
capName: "camera-grid-layout",
|
|
40051
|
+
capScope: "device",
|
|
40052
|
+
addonId: null,
|
|
40053
|
+
access: "create"
|
|
40054
|
+
},
|
|
40055
|
+
"cameraGridLayout.getDeviceLiveContribution": {
|
|
40056
|
+
capName: "camera-grid-layout",
|
|
40057
|
+
capScope: "device",
|
|
40058
|
+
addonId: null,
|
|
40059
|
+
access: "view"
|
|
40060
|
+
},
|
|
40061
|
+
"cameraGridLayout.getDeviceSettingsContribution": {
|
|
40062
|
+
capName: "camera-grid-layout",
|
|
40063
|
+
capScope: "device",
|
|
40064
|
+
addonId: null,
|
|
40065
|
+
access: "view"
|
|
40066
|
+
},
|
|
37376
40067
|
"cameraGridLayout.getLayout": {
|
|
37377
40068
|
capName: "camera-grid-layout",
|
|
37378
40069
|
capScope: "device",
|
|
@@ -37385,6 +40076,24 @@ Object.freeze({
|
|
|
37385
40076
|
addonId: null,
|
|
37386
40077
|
access: "create"
|
|
37387
40078
|
},
|
|
40079
|
+
"cameraPipelineConfig.applyDeviceSettingsPatch": {
|
|
40080
|
+
capName: "camera-pipeline-config",
|
|
40081
|
+
capScope: "device",
|
|
40082
|
+
addonId: null,
|
|
40083
|
+
access: "create"
|
|
40084
|
+
},
|
|
40085
|
+
"cameraPipelineConfig.getDeviceLiveContribution": {
|
|
40086
|
+
capName: "camera-pipeline-config",
|
|
40087
|
+
capScope: "device",
|
|
40088
|
+
addonId: null,
|
|
40089
|
+
access: "view"
|
|
40090
|
+
},
|
|
40091
|
+
"cameraPipelineConfig.getDeviceSettingsContribution": {
|
|
40092
|
+
capName: "camera-pipeline-config",
|
|
40093
|
+
capScope: "device",
|
|
40094
|
+
addonId: null,
|
|
40095
|
+
access: "view"
|
|
40096
|
+
},
|
|
37388
40097
|
"cameraStreams.getBrokerStreams": {
|
|
37389
40098
|
capName: "camera-streams",
|
|
37390
40099
|
capScope: "device",
|
|
@@ -37415,6 +40124,18 @@ Object.freeze({
|
|
|
37415
40124
|
addonId: null,
|
|
37416
40125
|
access: "view"
|
|
37417
40126
|
},
|
|
40127
|
+
"carbonMonoxide.getStatus": {
|
|
40128
|
+
capName: "carbon-monoxide",
|
|
40129
|
+
capScope: "device",
|
|
40130
|
+
addonId: null,
|
|
40131
|
+
access: "view"
|
|
40132
|
+
},
|
|
40133
|
+
"climateControl.getStatus": {
|
|
40134
|
+
capName: "climate-control",
|
|
40135
|
+
capScope: "device",
|
|
40136
|
+
addonId: null,
|
|
40137
|
+
access: "view"
|
|
40138
|
+
},
|
|
37418
40139
|
"climateControl.setFanMode": {
|
|
37419
40140
|
capName: "climate-control",
|
|
37420
40141
|
capScope: "device",
|
|
@@ -37463,6 +40184,12 @@ Object.freeze({
|
|
|
37463
40184
|
addonId: null,
|
|
37464
40185
|
access: "create"
|
|
37465
40186
|
},
|
|
40187
|
+
"color.getStatus": {
|
|
40188
|
+
capName: "color",
|
|
40189
|
+
capScope: "device",
|
|
40190
|
+
addonId: null,
|
|
40191
|
+
access: "view"
|
|
40192
|
+
},
|
|
37466
40193
|
"color.setColor": {
|
|
37467
40194
|
capName: "color",
|
|
37468
40195
|
capScope: "device",
|
|
@@ -37481,12 +40208,36 @@ Object.freeze({
|
|
|
37481
40208
|
addonId: null,
|
|
37482
40209
|
access: "create"
|
|
37483
40210
|
},
|
|
40211
|
+
"connectivity.getStatus": {
|
|
40212
|
+
capName: "connectivity",
|
|
40213
|
+
capScope: "device",
|
|
40214
|
+
addonId: null,
|
|
40215
|
+
access: "view"
|
|
40216
|
+
},
|
|
40217
|
+
"consumables.getStatus": {
|
|
40218
|
+
capName: "consumables",
|
|
40219
|
+
capScope: "device",
|
|
40220
|
+
addonId: null,
|
|
40221
|
+
access: "view"
|
|
40222
|
+
},
|
|
37484
40223
|
"consumables.reset": {
|
|
37485
40224
|
capName: "consumables",
|
|
37486
40225
|
capScope: "device",
|
|
37487
40226
|
addonId: null,
|
|
37488
40227
|
access: "delete"
|
|
37489
40228
|
},
|
|
40229
|
+
"contact.getStatus": {
|
|
40230
|
+
capName: "contact",
|
|
40231
|
+
capScope: "device",
|
|
40232
|
+
addonId: null,
|
|
40233
|
+
access: "view"
|
|
40234
|
+
},
|
|
40235
|
+
"control.getStatus": {
|
|
40236
|
+
capName: "control",
|
|
40237
|
+
capScope: "device",
|
|
40238
|
+
addonId: null,
|
|
40239
|
+
access: "view"
|
|
40240
|
+
},
|
|
37490
40241
|
"control.setValue": {
|
|
37491
40242
|
capName: "control",
|
|
37492
40243
|
capScope: "device",
|
|
@@ -37553,6 +40304,12 @@ Object.freeze({
|
|
|
37553
40304
|
addonId: null,
|
|
37554
40305
|
access: "create"
|
|
37555
40306
|
},
|
|
40307
|
+
"cover.getStatus": {
|
|
40308
|
+
capName: "cover",
|
|
40309
|
+
capScope: "device",
|
|
40310
|
+
addonId: null,
|
|
40311
|
+
access: "view"
|
|
40312
|
+
},
|
|
37556
40313
|
"cover.open": {
|
|
37557
40314
|
capName: "cover",
|
|
37558
40315
|
capScope: "device",
|
|
@@ -37685,6 +40442,12 @@ Object.freeze({
|
|
|
37685
40442
|
addonId: null,
|
|
37686
40443
|
access: "view"
|
|
37687
40444
|
},
|
|
40445
|
+
"dayNight.getStatus": {
|
|
40446
|
+
capName: "day-night",
|
|
40447
|
+
capScope: "device",
|
|
40448
|
+
addonId: null,
|
|
40449
|
+
access: "view"
|
|
40450
|
+
},
|
|
37688
40451
|
"dayNight.setSettings": {
|
|
37689
40452
|
capName: "day-night",
|
|
37690
40453
|
capScope: "device",
|
|
@@ -37775,6 +40538,30 @@ Object.freeze({
|
|
|
37775
40538
|
addonId: null,
|
|
37776
40539
|
access: "view"
|
|
37777
40540
|
},
|
|
40541
|
+
"detectionPipeline.applyDeviceSettingsPatch": {
|
|
40542
|
+
capName: "detection-pipeline",
|
|
40543
|
+
capScope: "device",
|
|
40544
|
+
addonId: null,
|
|
40545
|
+
access: "create"
|
|
40546
|
+
},
|
|
40547
|
+
"detectionPipeline.getDeviceLiveContribution": {
|
|
40548
|
+
capName: "detection-pipeline",
|
|
40549
|
+
capScope: "device",
|
|
40550
|
+
addonId: null,
|
|
40551
|
+
access: "view"
|
|
40552
|
+
},
|
|
40553
|
+
"detectionPipeline.getDeviceSettingsContribution": {
|
|
40554
|
+
capName: "detection-pipeline",
|
|
40555
|
+
capScope: "device",
|
|
40556
|
+
addonId: null,
|
|
40557
|
+
access: "view"
|
|
40558
|
+
},
|
|
40559
|
+
"deviceAdminLink.getAdminLink": {
|
|
40560
|
+
capName: "device-admin-link",
|
|
40561
|
+
capScope: "device",
|
|
40562
|
+
addonId: null,
|
|
40563
|
+
access: "view"
|
|
40564
|
+
},
|
|
37778
40565
|
"deviceAdoption.adopt": {
|
|
37779
40566
|
capName: "device-adoption",
|
|
37780
40567
|
capScope: "system",
|
|
@@ -37787,6 +40574,12 @@ Object.freeze({
|
|
|
37787
40574
|
addonId: null,
|
|
37788
40575
|
access: "view"
|
|
37789
40576
|
},
|
|
40577
|
+
"deviceAdoption.getStatus": {
|
|
40578
|
+
capName: "device-adoption",
|
|
40579
|
+
capScope: "system",
|
|
40580
|
+
addonId: null,
|
|
40581
|
+
access: "view"
|
|
40582
|
+
},
|
|
37790
40583
|
"deviceAdoption.listCandidateFilters": {
|
|
37791
40584
|
capName: "device-adoption",
|
|
37792
40585
|
capScope: "system",
|
|
@@ -37823,6 +40616,12 @@ Object.freeze({
|
|
|
37823
40616
|
addonId: null,
|
|
37824
40617
|
access: "create"
|
|
37825
40618
|
},
|
|
40619
|
+
"deviceDiscovery.getStatus": {
|
|
40620
|
+
capName: "device-discovery",
|
|
40621
|
+
capScope: "device",
|
|
40622
|
+
addonId: null,
|
|
40623
|
+
access: "view"
|
|
40624
|
+
},
|
|
37826
40625
|
"deviceDiscovery.listDiscovered": {
|
|
37827
40626
|
capName: "device-discovery",
|
|
37828
40627
|
capScope: "device",
|
|
@@ -37841,12 +40640,30 @@ Object.freeze({
|
|
|
37841
40640
|
addonId: null,
|
|
37842
40641
|
access: "create"
|
|
37843
40642
|
},
|
|
40643
|
+
"deviceExport.applyDeviceSettingsPatch": {
|
|
40644
|
+
capName: "device-export",
|
|
40645
|
+
capScope: "system",
|
|
40646
|
+
addonId: null,
|
|
40647
|
+
access: "create"
|
|
40648
|
+
},
|
|
37844
40649
|
"deviceExport.exposeDevice": {
|
|
37845
40650
|
capName: "device-export",
|
|
37846
40651
|
capScope: "system",
|
|
37847
40652
|
addonId: null,
|
|
37848
40653
|
access: "create"
|
|
37849
40654
|
},
|
|
40655
|
+
"deviceExport.getDeviceLiveContribution": {
|
|
40656
|
+
capName: "device-export",
|
|
40657
|
+
capScope: "system",
|
|
40658
|
+
addonId: null,
|
|
40659
|
+
access: "view"
|
|
40660
|
+
},
|
|
40661
|
+
"deviceExport.getDeviceSettingsContribution": {
|
|
40662
|
+
capName: "device-export",
|
|
40663
|
+
capScope: "system",
|
|
40664
|
+
addonId: null,
|
|
40665
|
+
access: "view"
|
|
40666
|
+
},
|
|
37850
40667
|
"deviceExport.getStatus": {
|
|
37851
40668
|
capName: "device-export",
|
|
37852
40669
|
capScope: "system",
|
|
@@ -37943,6 +40760,12 @@ Object.freeze({
|
|
|
37943
40760
|
addonId: null,
|
|
37944
40761
|
access: "create"
|
|
37945
40762
|
},
|
|
40763
|
+
"deviceManager.applyDeviceSettingsPatch": {
|
|
40764
|
+
capName: "device-manager",
|
|
40765
|
+
capScope: "system",
|
|
40766
|
+
addonId: null,
|
|
40767
|
+
access: "create"
|
|
40768
|
+
},
|
|
37946
40769
|
"deviceManager.applyInitialMeta": {
|
|
37947
40770
|
capName: "device-manager",
|
|
37948
40771
|
capScope: "system",
|
|
@@ -38045,6 +40868,12 @@ Object.freeze({
|
|
|
38045
40868
|
addonId: null,
|
|
38046
40869
|
access: "view"
|
|
38047
40870
|
},
|
|
40871
|
+
"deviceManager.getDeviceLiveContribution": {
|
|
40872
|
+
capName: "device-manager",
|
|
40873
|
+
capScope: "system",
|
|
40874
|
+
addonId: null,
|
|
40875
|
+
access: "view"
|
|
40876
|
+
},
|
|
38048
40877
|
"deviceManager.getDeviceLiveInfoAggregate": {
|
|
38049
40878
|
capName: "device-manager",
|
|
38050
40879
|
capScope: "system",
|
|
@@ -38057,6 +40886,12 @@ Object.freeze({
|
|
|
38057
40886
|
addonId: null,
|
|
38058
40887
|
access: "view"
|
|
38059
40888
|
},
|
|
40889
|
+
"deviceManager.getDeviceSettingsContribution": {
|
|
40890
|
+
capName: "device-manager",
|
|
40891
|
+
capScope: "system",
|
|
40892
|
+
addonId: null,
|
|
40893
|
+
access: "view"
|
|
40894
|
+
},
|
|
38060
40895
|
"deviceManager.getDeviceStatusAggregate": {
|
|
38061
40896
|
capName: "device-manager",
|
|
38062
40897
|
capScope: "system",
|
|
@@ -38549,6 +41384,36 @@ Object.freeze({
|
|
|
38549
41384
|
addonId: null,
|
|
38550
41385
|
access: "create"
|
|
38551
41386
|
},
|
|
41387
|
+
"deviceStatus.getStatus": {
|
|
41388
|
+
capName: "device-status",
|
|
41389
|
+
capScope: "device",
|
|
41390
|
+
addonId: null,
|
|
41391
|
+
access: "view"
|
|
41392
|
+
},
|
|
41393
|
+
"doorbell.applyDeviceSettingsPatch": {
|
|
41394
|
+
capName: "doorbell",
|
|
41395
|
+
capScope: "device",
|
|
41396
|
+
addonId: null,
|
|
41397
|
+
access: "create"
|
|
41398
|
+
},
|
|
41399
|
+
"doorbell.getDeviceLiveContribution": {
|
|
41400
|
+
capName: "doorbell",
|
|
41401
|
+
capScope: "device",
|
|
41402
|
+
addonId: null,
|
|
41403
|
+
access: "view"
|
|
41404
|
+
},
|
|
41405
|
+
"doorbell.getDeviceSettingsContribution": {
|
|
41406
|
+
capName: "doorbell",
|
|
41407
|
+
capScope: "device",
|
|
41408
|
+
addonId: null,
|
|
41409
|
+
access: "view"
|
|
41410
|
+
},
|
|
41411
|
+
"doorbell.getStatus": {
|
|
41412
|
+
capName: "doorbell",
|
|
41413
|
+
capScope: "device",
|
|
41414
|
+
addonId: null,
|
|
41415
|
+
access: "view"
|
|
41416
|
+
},
|
|
38552
41417
|
"embeddingEncoder.encode": {
|
|
38553
41418
|
capName: "embedding-encoder",
|
|
38554
41419
|
capScope: "system",
|
|
@@ -38567,6 +41432,18 @@ Object.freeze({
|
|
|
38567
41432
|
addonId: null,
|
|
38568
41433
|
access: "view"
|
|
38569
41434
|
},
|
|
41435
|
+
"enumSensor.getStatus": {
|
|
41436
|
+
capName: "enum-sensor",
|
|
41437
|
+
capScope: "device",
|
|
41438
|
+
addonId: null,
|
|
41439
|
+
access: "view"
|
|
41440
|
+
},
|
|
41441
|
+
"eventEmitter.getStatus": {
|
|
41442
|
+
capName: "event-emitter",
|
|
41443
|
+
capScope: "device",
|
|
41444
|
+
addonId: null,
|
|
41445
|
+
access: "view"
|
|
41446
|
+
},
|
|
38570
41447
|
"events.getEventClipUrl": {
|
|
38571
41448
|
capName: "events",
|
|
38572
41449
|
capScope: "device",
|
|
@@ -38687,6 +41564,12 @@ Object.freeze({
|
|
|
38687
41564
|
addonId: null,
|
|
38688
41565
|
access: "view"
|
|
38689
41566
|
},
|
|
41567
|
+
"fanControl.getStatus": {
|
|
41568
|
+
capName: "fan-control",
|
|
41569
|
+
capScope: "device",
|
|
41570
|
+
addonId: null,
|
|
41571
|
+
access: "view"
|
|
41572
|
+
},
|
|
38690
41573
|
"fanControl.setDirection": {
|
|
38691
41574
|
capName: "fan-control",
|
|
38692
41575
|
capScope: "device",
|
|
@@ -38711,6 +41594,12 @@ Object.freeze({
|
|
|
38711
41594
|
addonId: null,
|
|
38712
41595
|
access: "create"
|
|
38713
41596
|
},
|
|
41597
|
+
"featureProbe.getStatus": {
|
|
41598
|
+
capName: "feature-probe",
|
|
41599
|
+
capScope: "device",
|
|
41600
|
+
addonId: null,
|
|
41601
|
+
access: "view"
|
|
41602
|
+
},
|
|
38714
41603
|
"filesystemBrowse.browse": {
|
|
38715
41604
|
capName: "filesystem-browse",
|
|
38716
41605
|
capScope: "system",
|
|
@@ -38729,6 +41618,24 @@ Object.freeze({
|
|
|
38729
41618
|
addonId: null,
|
|
38730
41619
|
access: "view"
|
|
38731
41620
|
},
|
|
41621
|
+
"flood.getStatus": {
|
|
41622
|
+
capName: "flood",
|
|
41623
|
+
capScope: "device",
|
|
41624
|
+
addonId: null,
|
|
41625
|
+
access: "view"
|
|
41626
|
+
},
|
|
41627
|
+
"gas.getStatus": {
|
|
41628
|
+
capName: "gas",
|
|
41629
|
+
capScope: "device",
|
|
41630
|
+
addonId: null,
|
|
41631
|
+
access: "view"
|
|
41632
|
+
},
|
|
41633
|
+
"humidifier.getStatus": {
|
|
41634
|
+
capName: "humidifier",
|
|
41635
|
+
capScope: "device",
|
|
41636
|
+
addonId: null,
|
|
41637
|
+
access: "view"
|
|
41638
|
+
},
|
|
38732
41639
|
"humidifier.setMode": {
|
|
38733
41640
|
capName: "humidifier",
|
|
38734
41641
|
capScope: "device",
|
|
@@ -38747,12 +41654,30 @@ Object.freeze({
|
|
|
38747
41654
|
addonId: null,
|
|
38748
41655
|
access: "create"
|
|
38749
41656
|
},
|
|
41657
|
+
"humiditySensor.getStatus": {
|
|
41658
|
+
capName: "humidity-sensor",
|
|
41659
|
+
capScope: "device",
|
|
41660
|
+
addonId: null,
|
|
41661
|
+
access: "view"
|
|
41662
|
+
},
|
|
41663
|
+
"image.getStatus": {
|
|
41664
|
+
capName: "image",
|
|
41665
|
+
capScope: "device",
|
|
41666
|
+
addonId: null,
|
|
41667
|
+
access: "view"
|
|
41668
|
+
},
|
|
38750
41669
|
"imageSettings.getOptions": {
|
|
38751
41670
|
capName: "image-settings",
|
|
38752
41671
|
capScope: "device",
|
|
38753
41672
|
addonId: null,
|
|
38754
41673
|
access: "view"
|
|
38755
41674
|
},
|
|
41675
|
+
"imageSettings.getStatus": {
|
|
41676
|
+
capName: "image-settings",
|
|
41677
|
+
capScope: "device",
|
|
41678
|
+
addonId: null,
|
|
41679
|
+
access: "view"
|
|
41680
|
+
},
|
|
38756
41681
|
"imageSettings.setSettings": {
|
|
38757
41682
|
capName: "image-settings",
|
|
38758
41683
|
capScope: "device",
|
|
@@ -38825,6 +41750,12 @@ Object.freeze({
|
|
|
38825
41750
|
addonId: null,
|
|
38826
41751
|
access: "create"
|
|
38827
41752
|
},
|
|
41753
|
+
"intercom.getStatus": {
|
|
41754
|
+
capName: "intercom",
|
|
41755
|
+
capScope: "device",
|
|
41756
|
+
addonId: null,
|
|
41757
|
+
access: "view"
|
|
41758
|
+
},
|
|
38828
41759
|
"intercom.handleAnswer": {
|
|
38829
41760
|
capName: "intercom",
|
|
38830
41761
|
capScope: "device",
|
|
@@ -38861,6 +41792,12 @@ Object.freeze({
|
|
|
38861
41792
|
addonId: null,
|
|
38862
41793
|
access: "create"
|
|
38863
41794
|
},
|
|
41795
|
+
"lawnMowerControl.getStatus": {
|
|
41796
|
+
capName: "lawn-mower-control",
|
|
41797
|
+
capScope: "device",
|
|
41798
|
+
addonId: null,
|
|
41799
|
+
access: "view"
|
|
41800
|
+
},
|
|
38864
41801
|
"lawnMowerControl.pause": {
|
|
38865
41802
|
capName: "lawn-mower-control",
|
|
38866
41803
|
capScope: "device",
|
|
@@ -39143,6 +42080,12 @@ Object.freeze({
|
|
|
39143
42080
|
addonId: null,
|
|
39144
42081
|
access: "create"
|
|
39145
42082
|
},
|
|
42083
|
+
"lockControl.getStatus": {
|
|
42084
|
+
capName: "lock-control",
|
|
42085
|
+
capScope: "device",
|
|
42086
|
+
addonId: null,
|
|
42087
|
+
access: "view"
|
|
42088
|
+
},
|
|
39146
42089
|
"lockControl.lock": {
|
|
39147
42090
|
capName: "lock-control",
|
|
39148
42091
|
capScope: "device",
|
|
@@ -39191,6 +42134,12 @@ Object.freeze({
|
|
|
39191
42134
|
addonId: null,
|
|
39192
42135
|
access: "view"
|
|
39193
42136
|
},
|
|
42137
|
+
"mediaPlayer.getStatus": {
|
|
42138
|
+
capName: "media-player",
|
|
42139
|
+
capScope: "device",
|
|
42140
|
+
addonId: null,
|
|
42141
|
+
access: "view"
|
|
42142
|
+
},
|
|
39194
42143
|
"mediaPlayer.next": {
|
|
39195
42144
|
capName: "media-player",
|
|
39196
42145
|
capScope: "device",
|
|
@@ -39383,6 +42332,12 @@ Object.freeze({
|
|
|
39383
42332
|
addonId: null,
|
|
39384
42333
|
access: "create"
|
|
39385
42334
|
},
|
|
42335
|
+
"motion.getStatus": {
|
|
42336
|
+
capName: "motion",
|
|
42337
|
+
capScope: "device",
|
|
42338
|
+
addonId: null,
|
|
42339
|
+
access: "view"
|
|
42340
|
+
},
|
|
39386
42341
|
"motion.isDetected": {
|
|
39387
42342
|
capName: "motion",
|
|
39388
42343
|
capScope: "device",
|
|
@@ -39395,6 +42350,24 @@ Object.freeze({
|
|
|
39395
42350
|
addonId: null,
|
|
39396
42351
|
access: "create"
|
|
39397
42352
|
},
|
|
42353
|
+
"motionDetection.applyDeviceSettingsPatch": {
|
|
42354
|
+
capName: "motion-detection",
|
|
42355
|
+
capScope: "device",
|
|
42356
|
+
addonId: null,
|
|
42357
|
+
access: "create"
|
|
42358
|
+
},
|
|
42359
|
+
"motionDetection.getDeviceLiveContribution": {
|
|
42360
|
+
capName: "motion-detection",
|
|
42361
|
+
capScope: "device",
|
|
42362
|
+
addonId: null,
|
|
42363
|
+
access: "view"
|
|
42364
|
+
},
|
|
42365
|
+
"motionDetection.getDeviceSettingsContribution": {
|
|
42366
|
+
capName: "motion-detection",
|
|
42367
|
+
capScope: "device",
|
|
42368
|
+
addonId: null,
|
|
42369
|
+
access: "view"
|
|
42370
|
+
},
|
|
39398
42371
|
"motionDetection.removeCamera": {
|
|
39399
42372
|
capName: "motion-detection",
|
|
39400
42373
|
capScope: "device",
|
|
@@ -39407,6 +42380,12 @@ Object.freeze({
|
|
|
39407
42380
|
addonId: null,
|
|
39408
42381
|
access: "delete"
|
|
39409
42382
|
},
|
|
42383
|
+
"motionTrigger.getStatus": {
|
|
42384
|
+
capName: "motion-trigger",
|
|
42385
|
+
capScope: "device",
|
|
42386
|
+
addonId: null,
|
|
42387
|
+
access: "view"
|
|
42388
|
+
},
|
|
39410
42389
|
"motionTrigger.setMotionTrigger": {
|
|
39411
42390
|
capName: "motion-trigger",
|
|
39412
42391
|
capScope: "device",
|
|
@@ -39419,6 +42398,12 @@ Object.freeze({
|
|
|
39419
42398
|
addonId: null,
|
|
39420
42399
|
access: "view"
|
|
39421
42400
|
},
|
|
42401
|
+
"motionZones.getStatus": {
|
|
42402
|
+
capName: "motion-zones",
|
|
42403
|
+
capScope: "device",
|
|
42404
|
+
addonId: null,
|
|
42405
|
+
access: "view"
|
|
42406
|
+
},
|
|
39422
42407
|
"motionZones.setZone": {
|
|
39423
42408
|
capName: "motion-zones",
|
|
39424
42409
|
capScope: "device",
|
|
@@ -39479,6 +42464,12 @@ Object.freeze({
|
|
|
39479
42464
|
addonId: null,
|
|
39480
42465
|
access: "view"
|
|
39481
42466
|
},
|
|
42467
|
+
"nativeObjectDetection.getStatus": {
|
|
42468
|
+
capName: "native-object-detection",
|
|
42469
|
+
capScope: "device",
|
|
42470
|
+
addonId: null,
|
|
42471
|
+
access: "view"
|
|
42472
|
+
},
|
|
39482
42473
|
"nativeObjectDetection.setEnabled": {
|
|
39483
42474
|
capName: "native-object-detection",
|
|
39484
42475
|
capScope: "device",
|
|
@@ -39497,6 +42488,12 @@ Object.freeze({
|
|
|
39497
42488
|
addonId: null,
|
|
39498
42489
|
access: "view"
|
|
39499
42490
|
},
|
|
42491
|
+
"navigation.getStatus": {
|
|
42492
|
+
capName: "navigation",
|
|
42493
|
+
capScope: "device",
|
|
42494
|
+
addonId: null,
|
|
42495
|
+
access: "view"
|
|
42496
|
+
},
|
|
39500
42497
|
"navigation.goToPoint": {
|
|
39501
42498
|
capName: "navigation",
|
|
39502
42499
|
capScope: "device",
|
|
@@ -39581,6 +42578,12 @@ Object.freeze({
|
|
|
39581
42578
|
addonId: null,
|
|
39582
42579
|
access: "create"
|
|
39583
42580
|
},
|
|
42581
|
+
"networkLink.getStatus": {
|
|
42582
|
+
capName: "network-link",
|
|
42583
|
+
capScope: "device",
|
|
42584
|
+
addonId: null,
|
|
42585
|
+
access: "view"
|
|
42586
|
+
},
|
|
39584
42587
|
"networkQuality.getAllStats": {
|
|
39585
42588
|
capName: "network-quality",
|
|
39586
42589
|
capScope: "system",
|
|
@@ -39839,18 +42842,36 @@ Object.freeze({
|
|
|
39839
42842
|
addonId: null,
|
|
39840
42843
|
access: "create"
|
|
39841
42844
|
},
|
|
42845
|
+
"notifier.getStatus": {
|
|
42846
|
+
capName: "notifier",
|
|
42847
|
+
capScope: "device",
|
|
42848
|
+
addonId: null,
|
|
42849
|
+
access: "view"
|
|
42850
|
+
},
|
|
39842
42851
|
"notifier.send": {
|
|
39843
42852
|
capName: "notifier",
|
|
39844
42853
|
capScope: "device",
|
|
39845
42854
|
addonId: null,
|
|
39846
42855
|
access: "create"
|
|
39847
42856
|
},
|
|
42857
|
+
"numericSensor.getStatus": {
|
|
42858
|
+
capName: "numeric-sensor",
|
|
42859
|
+
capScope: "device",
|
|
42860
|
+
addonId: null,
|
|
42861
|
+
access: "view"
|
|
42862
|
+
},
|
|
39848
42863
|
"oauthIntegration.getDescriptor": {
|
|
39849
42864
|
capName: "oauth-integration",
|
|
39850
42865
|
capScope: "system",
|
|
39851
42866
|
addonId: null,
|
|
39852
42867
|
access: "view"
|
|
39853
42868
|
},
|
|
42869
|
+
"osd.getStatus": {
|
|
42870
|
+
capName: "osd",
|
|
42871
|
+
capScope: "device",
|
|
42872
|
+
addonId: null,
|
|
42873
|
+
access: "view"
|
|
42874
|
+
},
|
|
39854
42875
|
"osd.setOverlay": {
|
|
39855
42876
|
capName: "osd",
|
|
39856
42877
|
capScope: "device",
|
|
@@ -39923,6 +42944,12 @@ Object.freeze({
|
|
|
39923
42944
|
addonId: null,
|
|
39924
42945
|
access: "create"
|
|
39925
42946
|
},
|
|
42947
|
+
"petFeeder.getStatus": {
|
|
42948
|
+
capName: "pet-feeder",
|
|
42949
|
+
capScope: "device",
|
|
42950
|
+
addonId: null,
|
|
42951
|
+
access: "view"
|
|
42952
|
+
},
|
|
39926
42953
|
"petFeeder.markFoodReplenished": {
|
|
39927
42954
|
capName: "pet-feeder",
|
|
39928
42955
|
capScope: "device",
|
|
@@ -39965,6 +42992,12 @@ Object.freeze({
|
|
|
39965
42992
|
addonId: null,
|
|
39966
42993
|
access: "create"
|
|
39967
42994
|
},
|
|
42995
|
+
"pipelineAnalytics.applyDeviceSettingsPatch": {
|
|
42996
|
+
capName: "pipeline-analytics",
|
|
42997
|
+
capScope: "device",
|
|
42998
|
+
addonId: null,
|
|
42999
|
+
access: "create"
|
|
43000
|
+
},
|
|
39968
43001
|
"pipelineAnalytics.cancelRelocateMedia": {
|
|
39969
43002
|
capName: "pipeline-analytics",
|
|
39970
43003
|
capScope: "device",
|
|
@@ -40031,6 +43064,18 @@ Object.freeze({
|
|
|
40031
43064
|
addonId: null,
|
|
40032
43065
|
access: "view"
|
|
40033
43066
|
},
|
|
43067
|
+
"pipelineAnalytics.getDeviceLiveContribution": {
|
|
43068
|
+
capName: "pipeline-analytics",
|
|
43069
|
+
capScope: "device",
|
|
43070
|
+
addonId: null,
|
|
43071
|
+
access: "view"
|
|
43072
|
+
},
|
|
43073
|
+
"pipelineAnalytics.getDeviceSettingsContribution": {
|
|
43074
|
+
capName: "pipeline-analytics",
|
|
43075
|
+
capScope: "device",
|
|
43076
|
+
addonId: null,
|
|
43077
|
+
access: "view"
|
|
43078
|
+
},
|
|
40034
43079
|
"pipelineAnalytics.getEventDensity": {
|
|
40035
43080
|
capName: "pipeline-analytics",
|
|
40036
43081
|
capScope: "device",
|
|
@@ -40241,6 +43286,12 @@ Object.freeze({
|
|
|
40241
43286
|
addonId: null,
|
|
40242
43287
|
access: "view"
|
|
40243
43288
|
},
|
|
43289
|
+
"pipelineAnalytics.ownersWithMedia": {
|
|
43290
|
+
capName: "pipeline-analytics",
|
|
43291
|
+
capScope: "device",
|
|
43292
|
+
addonId: null,
|
|
43293
|
+
access: "view"
|
|
43294
|
+
},
|
|
40244
43295
|
"pipelineAnalytics.pauseForStorageMigration": {
|
|
40245
43296
|
capName: "pipeline-analytics",
|
|
40246
43297
|
capScope: "device",
|
|
@@ -40595,6 +43646,12 @@ Object.freeze({
|
|
|
40595
43646
|
addonId: null,
|
|
40596
43647
|
access: "view"
|
|
40597
43648
|
},
|
|
43649
|
+
"pipelineOrchestrator.applyDeviceSettingsPatch": {
|
|
43650
|
+
capName: "pipeline-orchestrator",
|
|
43651
|
+
capScope: "system",
|
|
43652
|
+
addonId: null,
|
|
43653
|
+
access: "create"
|
|
43654
|
+
},
|
|
40598
43655
|
"pipelineOrchestrator.assignAudio": {
|
|
40599
43656
|
capName: "pipeline-orchestrator",
|
|
40600
43657
|
capScope: "system",
|
|
@@ -40685,6 +43742,18 @@ Object.freeze({
|
|
|
40685
43742
|
addonId: null,
|
|
40686
43743
|
access: "view"
|
|
40687
43744
|
},
|
|
43745
|
+
"pipelineOrchestrator.getDeviceLiveContribution": {
|
|
43746
|
+
capName: "pipeline-orchestrator",
|
|
43747
|
+
capScope: "system",
|
|
43748
|
+
addonId: null,
|
|
43749
|
+
access: "view"
|
|
43750
|
+
},
|
|
43751
|
+
"pipelineOrchestrator.getDeviceSettingsContribution": {
|
|
43752
|
+
capName: "pipeline-orchestrator",
|
|
43753
|
+
capScope: "system",
|
|
43754
|
+
addonId: null,
|
|
43755
|
+
access: "view"
|
|
43756
|
+
},
|
|
40688
43757
|
"pipelineOrchestrator.getGlobalMetrics": {
|
|
40689
43758
|
capName: "pipeline-orchestrator",
|
|
40690
43759
|
capScope: "system",
|
|
@@ -41093,12 +44162,36 @@ Object.freeze({
|
|
|
41093
44162
|
addonId: null,
|
|
41094
44163
|
access: "view"
|
|
41095
44164
|
},
|
|
44165
|
+
"powerMeter.getStatus": {
|
|
44166
|
+
capName: "power-meter",
|
|
44167
|
+
capScope: "device",
|
|
44168
|
+
addonId: null,
|
|
44169
|
+
access: "view"
|
|
44170
|
+
},
|
|
44171
|
+
"presence.getStatus": {
|
|
44172
|
+
capName: "presence",
|
|
44173
|
+
capScope: "device",
|
|
44174
|
+
addonId: null,
|
|
44175
|
+
access: "view"
|
|
44176
|
+
},
|
|
44177
|
+
"pressureSensor.getStatus": {
|
|
44178
|
+
capName: "pressure-sensor",
|
|
44179
|
+
capScope: "device",
|
|
44180
|
+
addonId: null,
|
|
44181
|
+
access: "view"
|
|
44182
|
+
},
|
|
41096
44183
|
"privacyMask.getOptions": {
|
|
41097
44184
|
capName: "privacy-mask",
|
|
41098
44185
|
capScope: "device",
|
|
41099
44186
|
addonId: null,
|
|
41100
44187
|
access: "view"
|
|
41101
44188
|
},
|
|
44189
|
+
"privacyMask.getStatus": {
|
|
44190
|
+
capName: "privacy-mask",
|
|
44191
|
+
capScope: "device",
|
|
44192
|
+
addonId: null,
|
|
44193
|
+
access: "view"
|
|
44194
|
+
},
|
|
41102
44195
|
"privacyMask.setAudioEnabled": {
|
|
41103
44196
|
capName: "privacy-mask",
|
|
41104
44197
|
capScope: "device",
|
|
@@ -41159,6 +44252,12 @@ Object.freeze({
|
|
|
41159
44252
|
addonId: null,
|
|
41160
44253
|
access: "view"
|
|
41161
44254
|
},
|
|
44255
|
+
"ptz.getStatus": {
|
|
44256
|
+
capName: "ptz",
|
|
44257
|
+
capScope: "device",
|
|
44258
|
+
addonId: null,
|
|
44259
|
+
access: "view"
|
|
44260
|
+
},
|
|
41162
44261
|
"ptz.goHome": {
|
|
41163
44262
|
capName: "ptz",
|
|
41164
44263
|
capScope: "device",
|
|
@@ -41237,6 +44336,12 @@ Object.freeze({
|
|
|
41237
44336
|
addonId: null,
|
|
41238
44337
|
access: "create"
|
|
41239
44338
|
},
|
|
44339
|
+
"recording.applyDeviceSettingsPatch": {
|
|
44340
|
+
capName: "recording",
|
|
44341
|
+
capScope: "system",
|
|
44342
|
+
addonId: null,
|
|
44343
|
+
access: "create"
|
|
44344
|
+
},
|
|
41240
44345
|
"recording.cancelRelocateJob": {
|
|
41241
44346
|
capName: "recording",
|
|
41242
44347
|
capScope: "system",
|
|
@@ -41285,6 +44390,18 @@ Object.freeze({
|
|
|
41285
44390
|
addonId: null,
|
|
41286
44391
|
access: "view"
|
|
41287
44392
|
},
|
|
44393
|
+
"recording.getDeviceLiveContribution": {
|
|
44394
|
+
capName: "recording",
|
|
44395
|
+
capScope: "system",
|
|
44396
|
+
addonId: null,
|
|
44397
|
+
access: "view"
|
|
44398
|
+
},
|
|
44399
|
+
"recording.getDeviceSettingsContribution": {
|
|
44400
|
+
capName: "recording",
|
|
44401
|
+
capScope: "system",
|
|
44402
|
+
addonId: null,
|
|
44403
|
+
access: "view"
|
|
44404
|
+
},
|
|
41288
44405
|
"recording.getPlacement": {
|
|
41289
44406
|
capName: "recording",
|
|
41290
44407
|
capScope: "system",
|
|
@@ -41303,6 +44420,12 @@ Object.freeze({
|
|
|
41303
44420
|
addonId: null,
|
|
41304
44421
|
access: "view"
|
|
41305
44422
|
},
|
|
44423
|
+
"recording.getStatus": {
|
|
44424
|
+
capName: "recording",
|
|
44425
|
+
capScope: "system",
|
|
44426
|
+
addonId: null,
|
|
44427
|
+
access: "view"
|
|
44428
|
+
},
|
|
41306
44429
|
"recording.getStorageMigrationMoveStatus": {
|
|
41307
44430
|
capName: "recording",
|
|
41308
44431
|
capScope: "system",
|
|
@@ -41477,6 +44600,24 @@ Object.freeze({
|
|
|
41477
44600
|
addonId: null,
|
|
41478
44601
|
access: "view"
|
|
41479
44602
|
},
|
|
44603
|
+
"recordingOnboard.getOptions": {
|
|
44604
|
+
capName: "recording-onboard",
|
|
44605
|
+
capScope: "device",
|
|
44606
|
+
addonId: null,
|
|
44607
|
+
access: "view"
|
|
44608
|
+
},
|
|
44609
|
+
"recordingOnboard.getStatus": {
|
|
44610
|
+
capName: "recording-onboard",
|
|
44611
|
+
capScope: "device",
|
|
44612
|
+
addonId: null,
|
|
44613
|
+
access: "view"
|
|
44614
|
+
},
|
|
44615
|
+
"recordingOnboard.setSettings": {
|
|
44616
|
+
capName: "recording-onboard",
|
|
44617
|
+
capScope: "device",
|
|
44618
|
+
addonId: null,
|
|
44619
|
+
access: "create"
|
|
44620
|
+
},
|
|
41480
44621
|
"recordingSignal.getStatus": {
|
|
41481
44622
|
capName: "recording-signal",
|
|
41482
44623
|
capScope: "device",
|
|
@@ -41507,6 +44648,12 @@ Object.freeze({
|
|
|
41507
44648
|
addonId: null,
|
|
41508
44649
|
access: "delete"
|
|
41509
44650
|
},
|
|
44651
|
+
"sceneMonitor.getStatus": {
|
|
44652
|
+
capName: "scene-monitor",
|
|
44653
|
+
capScope: "device",
|
|
44654
|
+
addonId: null,
|
|
44655
|
+
access: "view"
|
|
44656
|
+
},
|
|
41510
44657
|
"sceneMonitor.listScenes": {
|
|
41511
44658
|
capName: "scene-monitor",
|
|
41512
44659
|
capScope: "device",
|
|
@@ -41537,6 +44684,12 @@ Object.freeze({
|
|
|
41537
44684
|
addonId: null,
|
|
41538
44685
|
access: "create"
|
|
41539
44686
|
},
|
|
44687
|
+
"scriptRunner.getStatus": {
|
|
44688
|
+
capName: "script-runner",
|
|
44689
|
+
capScope: "device",
|
|
44690
|
+
addonId: null,
|
|
44691
|
+
access: "view"
|
|
44692
|
+
},
|
|
41540
44693
|
"scriptRunner.run": {
|
|
41541
44694
|
capName: "script-runner",
|
|
41542
44695
|
capScope: "device",
|
|
@@ -41669,6 +44822,12 @@ Object.freeze({
|
|
|
41669
44822
|
addonId: null,
|
|
41670
44823
|
access: "create"
|
|
41671
44824
|
},
|
|
44825
|
+
"smoke.getStatus": {
|
|
44826
|
+
capName: "smoke",
|
|
44827
|
+
capScope: "device",
|
|
44828
|
+
addonId: null,
|
|
44829
|
+
access: "view"
|
|
44830
|
+
},
|
|
41672
44831
|
"smtpProvider.getStatus": {
|
|
41673
44832
|
capName: "smtp-provider",
|
|
41674
44833
|
capScope: "system",
|
|
@@ -41687,12 +44846,30 @@ Object.freeze({
|
|
|
41687
44846
|
addonId: null,
|
|
41688
44847
|
access: "view"
|
|
41689
44848
|
},
|
|
44849
|
+
"snapshot.applyDeviceSettingsPatch": {
|
|
44850
|
+
capName: "snapshot",
|
|
44851
|
+
capScope: "device",
|
|
44852
|
+
addonId: null,
|
|
44853
|
+
access: "create"
|
|
44854
|
+
},
|
|
41690
44855
|
"snapshot.getDebugState": {
|
|
41691
44856
|
capName: "snapshot",
|
|
41692
44857
|
capScope: "device",
|
|
41693
44858
|
addonId: null,
|
|
41694
44859
|
access: "view"
|
|
41695
44860
|
},
|
|
44861
|
+
"snapshot.getDeviceLiveContribution": {
|
|
44862
|
+
capName: "snapshot",
|
|
44863
|
+
capScope: "device",
|
|
44864
|
+
addonId: null,
|
|
44865
|
+
access: "view"
|
|
44866
|
+
},
|
|
44867
|
+
"snapshot.getDeviceSettingsContribution": {
|
|
44868
|
+
capName: "snapshot",
|
|
44869
|
+
capScope: "device",
|
|
44870
|
+
addonId: null,
|
|
44871
|
+
access: "view"
|
|
44872
|
+
},
|
|
41696
44873
|
"snapshot.getSnapshot": {
|
|
41697
44874
|
capName: "snapshot",
|
|
41698
44875
|
capScope: "device",
|
|
@@ -41711,6 +44888,12 @@ Object.freeze({
|
|
|
41711
44888
|
addonId: null,
|
|
41712
44889
|
access: "view"
|
|
41713
44890
|
},
|
|
44891
|
+
"snapshot.getStatus": {
|
|
44892
|
+
capName: "snapshot",
|
|
44893
|
+
capScope: "device",
|
|
44894
|
+
addonId: null,
|
|
44895
|
+
access: "view"
|
|
44896
|
+
},
|
|
41714
44897
|
"snapshot.invalidateCache": {
|
|
41715
44898
|
capName: "snapshot",
|
|
41716
44899
|
capScope: "device",
|
|
@@ -42047,6 +45230,12 @@ Object.freeze({
|
|
|
42047
45230
|
addonId: null,
|
|
42048
45231
|
access: "create"
|
|
42049
45232
|
},
|
|
45233
|
+
"streamBroker.applyDeviceSettingsPatch": {
|
|
45234
|
+
capName: "stream-broker",
|
|
45235
|
+
capScope: "system",
|
|
45236
|
+
addonId: null,
|
|
45237
|
+
access: "create"
|
|
45238
|
+
},
|
|
42050
45239
|
"streamBroker.assignProfile": {
|
|
42051
45240
|
capName: "stream-broker",
|
|
42052
45241
|
capScope: "system",
|
|
@@ -42083,6 +45272,18 @@ Object.freeze({
|
|
|
42083
45272
|
addonId: null,
|
|
42084
45273
|
access: "view"
|
|
42085
45274
|
},
|
|
45275
|
+
"streamBroker.getDeviceLiveContribution": {
|
|
45276
|
+
capName: "stream-broker",
|
|
45277
|
+
capScope: "system",
|
|
45278
|
+
addonId: null,
|
|
45279
|
+
access: "view"
|
|
45280
|
+
},
|
|
45281
|
+
"streamBroker.getDeviceSettingsContribution": {
|
|
45282
|
+
capName: "stream-broker",
|
|
45283
|
+
capScope: "system",
|
|
45284
|
+
addonId: null,
|
|
45285
|
+
access: "view"
|
|
45286
|
+
},
|
|
42086
45287
|
"streamBroker.getPreBufferInfo": {
|
|
42087
45288
|
capName: "stream-broker",
|
|
42088
45289
|
capScope: "system",
|
|
@@ -42281,6 +45482,12 @@ Object.freeze({
|
|
|
42281
45482
|
addonId: null,
|
|
42282
45483
|
access: "view"
|
|
42283
45484
|
},
|
|
45485
|
+
"streamParams.getStatus": {
|
|
45486
|
+
capName: "stream-params",
|
|
45487
|
+
capScope: "device",
|
|
45488
|
+
addonId: null,
|
|
45489
|
+
access: "view"
|
|
45490
|
+
},
|
|
42284
45491
|
"streamParams.setProfile": {
|
|
42285
45492
|
capName: "stream-params",
|
|
42286
45493
|
capScope: "device",
|
|
@@ -42293,6 +45500,12 @@ Object.freeze({
|
|
|
42293
45500
|
addonId: null,
|
|
42294
45501
|
access: "view"
|
|
42295
45502
|
},
|
|
45503
|
+
"switch.getStatus": {
|
|
45504
|
+
capName: "switch",
|
|
45505
|
+
capScope: "device",
|
|
45506
|
+
addonId: null,
|
|
45507
|
+
access: "view"
|
|
45508
|
+
},
|
|
42296
45509
|
"switch.setState": {
|
|
42297
45510
|
capName: "switch",
|
|
42298
45511
|
capScope: "device",
|
|
@@ -42389,6 +45602,18 @@ Object.freeze({
|
|
|
42389
45602
|
addonId: null,
|
|
42390
45603
|
access: "create"
|
|
42391
45604
|
},
|
|
45605
|
+
"tamper.getStatus": {
|
|
45606
|
+
capName: "tamper",
|
|
45607
|
+
capScope: "device",
|
|
45608
|
+
addonId: null,
|
|
45609
|
+
access: "view"
|
|
45610
|
+
},
|
|
45611
|
+
"temperatureSensor.getStatus": {
|
|
45612
|
+
capName: "temperature-sensor",
|
|
45613
|
+
capScope: "device",
|
|
45614
|
+
addonId: null,
|
|
45615
|
+
access: "view"
|
|
45616
|
+
},
|
|
42392
45617
|
"terminalSession.adoptLegacyMonitor": {
|
|
42393
45618
|
capName: "terminal-session",
|
|
42394
45619
|
capScope: "system",
|
|
@@ -42485,6 +45710,12 @@ Object.freeze({
|
|
|
42485
45710
|
addonId: null,
|
|
42486
45711
|
access: "view"
|
|
42487
45712
|
},
|
|
45713
|
+
"update.getStatus": {
|
|
45714
|
+
capName: "update",
|
|
45715
|
+
capScope: "device",
|
|
45716
|
+
addonId: null,
|
|
45717
|
+
access: "view"
|
|
45718
|
+
},
|
|
42488
45719
|
"update.installUpdate": {
|
|
42489
45720
|
capName: "update",
|
|
42490
45721
|
capScope: "device",
|
|
@@ -42707,6 +45938,12 @@ Object.freeze({
|
|
|
42707
45938
|
addonId: null,
|
|
42708
45939
|
access: "create"
|
|
42709
45940
|
},
|
|
45941
|
+
"vacuumControl.getStatus": {
|
|
45942
|
+
capName: "vacuum-control",
|
|
45943
|
+
capScope: "device",
|
|
45944
|
+
addonId: null,
|
|
45945
|
+
access: "view"
|
|
45946
|
+
},
|
|
42710
45947
|
"vacuumControl.locate": {
|
|
42711
45948
|
capName: "vacuum-control",
|
|
42712
45949
|
capScope: "device",
|
|
@@ -42749,6 +45986,12 @@ Object.freeze({
|
|
|
42749
45986
|
addonId: null,
|
|
42750
45987
|
access: "create"
|
|
42751
45988
|
},
|
|
45989
|
+
"valve.getStatus": {
|
|
45990
|
+
capName: "valve",
|
|
45991
|
+
capScope: "device",
|
|
45992
|
+
addonId: null,
|
|
45993
|
+
access: "view"
|
|
45994
|
+
},
|
|
42752
45995
|
"valve.open": {
|
|
42753
45996
|
capName: "valve",
|
|
42754
45997
|
capScope: "device",
|
|
@@ -42821,6 +46064,18 @@ Object.freeze({
|
|
|
42821
46064
|
addonId: null,
|
|
42822
46065
|
access: "create"
|
|
42823
46066
|
},
|
|
46067
|
+
"vibration.getStatus": {
|
|
46068
|
+
capName: "vibration",
|
|
46069
|
+
capScope: "device",
|
|
46070
|
+
addonId: null,
|
|
46071
|
+
access: "view"
|
|
46072
|
+
},
|
|
46073
|
+
"videoclips.dialClipStream": {
|
|
46074
|
+
capName: "videoclips",
|
|
46075
|
+
capScope: "device",
|
|
46076
|
+
addonId: null,
|
|
46077
|
+
access: "view"
|
|
46078
|
+
},
|
|
42824
46079
|
"videoclips.getClipPlayback": {
|
|
42825
46080
|
capName: "videoclips",
|
|
42826
46081
|
capScope: "device",
|
|
@@ -42833,6 +46088,18 @@ Object.freeze({
|
|
|
42833
46088
|
addonId: null,
|
|
42834
46089
|
access: "view"
|
|
42835
46090
|
},
|
|
46091
|
+
"videoclips.listSources": {
|
|
46092
|
+
capName: "videoclips",
|
|
46093
|
+
capScope: "device",
|
|
46094
|
+
addonId: null,
|
|
46095
|
+
access: "view"
|
|
46096
|
+
},
|
|
46097
|
+
"videoclips.readClipBytes": {
|
|
46098
|
+
capName: "videoclips",
|
|
46099
|
+
capScope: "device",
|
|
46100
|
+
addonId: null,
|
|
46101
|
+
access: "view"
|
|
46102
|
+
},
|
|
42836
46103
|
"viewerUi.getStaticDir": {
|
|
42837
46104
|
capName: "viewer-ui",
|
|
42838
46105
|
capScope: "system",
|
|
@@ -42845,6 +46112,12 @@ Object.freeze({
|
|
|
42845
46112
|
addonId: null,
|
|
42846
46113
|
access: "view"
|
|
42847
46114
|
},
|
|
46115
|
+
"waterHeater.getStatus": {
|
|
46116
|
+
capName: "water-heater",
|
|
46117
|
+
capScope: "device",
|
|
46118
|
+
addonId: null,
|
|
46119
|
+
access: "view"
|
|
46120
|
+
},
|
|
42848
46121
|
"waterHeater.setAway": {
|
|
42849
46122
|
capName: "water-heater",
|
|
42850
46123
|
capScope: "device",
|
|
@@ -42863,6 +46136,12 @@ Object.freeze({
|
|
|
42863
46136
|
addonId: null,
|
|
42864
46137
|
access: "create"
|
|
42865
46138
|
},
|
|
46139
|
+
"weather.getStatus": {
|
|
46140
|
+
capName: "weather",
|
|
46141
|
+
capScope: "device",
|
|
46142
|
+
addonId: null,
|
|
46143
|
+
access: "view"
|
|
46144
|
+
},
|
|
42866
46145
|
"webrtcSession.addIceCandidate": {
|
|
42867
46146
|
capName: "webrtc-session",
|
|
42868
46147
|
capScope: "device",
|
|
@@ -43225,6 +46504,11 @@ Object.freeze({
|
|
|
43225
46504
|
form: "single",
|
|
43226
46505
|
optional: true
|
|
43227
46506
|
}],
|
|
46507
|
+
"deviceAdminLink.getAdminLink": [{
|
|
46508
|
+
name: "deviceId",
|
|
46509
|
+
form: "single",
|
|
46510
|
+
optional: false
|
|
46511
|
+
}],
|
|
43228
46512
|
"deviceAdoption.release": [{
|
|
43229
46513
|
name: "camDeviceId",
|
|
43230
46514
|
form: "single",
|
|
@@ -44135,6 +47419,11 @@ Object.freeze({
|
|
|
44135
47419
|
form: "single",
|
|
44136
47420
|
optional: false
|
|
44137
47421
|
}],
|
|
47422
|
+
"pipelineAnalytics.ownersWithMedia": [{
|
|
47423
|
+
name: "deviceId",
|
|
47424
|
+
form: "single",
|
|
47425
|
+
optional: false
|
|
47426
|
+
}],
|
|
44138
47427
|
"pipelineAnalytics.proposeRetrainAnnotations": [{
|
|
44139
47428
|
name: "deviceId",
|
|
44140
47429
|
form: "single",
|
|
@@ -44605,6 +47894,16 @@ Object.freeze({
|
|
|
44605
47894
|
form: "single",
|
|
44606
47895
|
optional: true
|
|
44607
47896
|
}],
|
|
47897
|
+
"recordingOnboard.getOptions": [{
|
|
47898
|
+
name: "deviceId",
|
|
47899
|
+
form: "single",
|
|
47900
|
+
optional: false
|
|
47901
|
+
}],
|
|
47902
|
+
"recordingOnboard.setSettings": [{
|
|
47903
|
+
name: "deviceId",
|
|
47904
|
+
form: "single",
|
|
47905
|
+
optional: false
|
|
47906
|
+
}],
|
|
44608
47907
|
"recordingSignal.getStatus": [{
|
|
44609
47908
|
name: "deviceId",
|
|
44610
47909
|
form: "single",
|
|
@@ -44831,6 +48130,11 @@ Object.freeze({
|
|
|
44831
48130
|
form: "single",
|
|
44832
48131
|
optional: false
|
|
44833
48132
|
}],
|
|
48133
|
+
"videoclips.dialClipStream": [{
|
|
48134
|
+
name: "deviceId",
|
|
48135
|
+
form: "single",
|
|
48136
|
+
optional: false
|
|
48137
|
+
}],
|
|
44834
48138
|
"videoclips.getClipPlayback": [{
|
|
44835
48139
|
name: "deviceId",
|
|
44836
48140
|
form: "single",
|
|
@@ -44841,6 +48145,16 @@ Object.freeze({
|
|
|
44841
48145
|
form: "single",
|
|
44842
48146
|
optional: false
|
|
44843
48147
|
}],
|
|
48148
|
+
"videoclips.listSources": [{
|
|
48149
|
+
name: "deviceId",
|
|
48150
|
+
form: "single",
|
|
48151
|
+
optional: false
|
|
48152
|
+
}],
|
|
48153
|
+
"videoclips.readClipBytes": [{
|
|
48154
|
+
name: "deviceId",
|
|
48155
|
+
form: "single",
|
|
48156
|
+
optional: false
|
|
48157
|
+
}],
|
|
44844
48158
|
"waterHeater.setAway": [{
|
|
44845
48159
|
name: "deviceId",
|
|
44846
48160
|
form: "single",
|
|
@@ -45759,4 +49073,4 @@ function bestLocationMatch(externalName, existing, threshold = .8) {
|
|
|
45759
49073
|
var MB = 1024 * 1024;
|
|
45760
49074
|
1024 * MB, 3072 * MB;
|
|
45761
49075
|
//#endregion
|
|
45762
|
-
export {
|
|
49076
|
+
export { parseAdminBase as $, contactCapability as A, union as At, gasCapability as B, buildAddonRouteProvider as C, array as Ct, climateControlCapability as D, object as Dt, carbonMonoxideCapability as E, number as Et, deviceExportCapability as F, lockControlCapability as G, humiditySensorCapability as H, enumSensorCapability as I, normalizeUnit as J, mediaPlayerCapability as K, eventEmitterCapability as L, coverCapability as M, url as Mt, deviceAdminLinkCapability as N, EventCategory as Nt, colorCapability as O, record as Ot, deviceAdoptionCapability as P, oauthIntegrationCapability as Q, fanControlCapability as R, brokerCapability as S, _enum as St, buttonCapability as T, literal as Tt, imageCapability as U, humidifierCapability as V, lawnMowerControlCapability as W, notifierCapability as X, notificationOutputCapability as Y, numericSensorCapability as Z, automationControlCapability as _, DeviceFeature as _t, COCO_TO_MACRO as a, smokeCapability as at, binaryCapability as b, createEvent as bt, FanDirectionSchema as c, temperatureSensorCapability as ct, TargetSchema as d, valveCapability as dt, powerMeterCapability as et, accessoriesCapability as f, vibrationCapability as ft, ambientLightSensorCapability as g, BaseAddon as gt, alarmPanelCapability as h, errMsg as ht, CAMERA_SWITCH_ORDER as i, scriptRunnerCapability as it, controlCapability as j, unknown as jt, connectivityCapability as k, string as kt, HvacModeSchema as l, updateCapability as lt, airQualitySensorCapability as m, weatherCapability as mt, BaseDevice as n, presenceCapability as nt, CameraSwitchIdSchema as o, switchCapability as ot, addonRoutesCapability as p, waterHeaterCapability as pt, motionCapability as q, BaseDeviceProvider as r, pressureSensorCapability as rt, EnumSensorDateTimeFormatSchema as s, tamperCapability as st, AlarmArmModeSchema as t, prepareNotification as tt, MediaPlayerRepeatSchema as u, vacuumControlCapability as ut, batteryCapability as v, DeviceRole as vt, buildDeviceAdminUrl as w, discriminatedUnion as wt, brightnessCapability as x, nodePin as xt, bestLocationMatch as y, DeviceType as yt, floodCapability as z };
|