@camstack/addon-provider-homeassistant 1.2.659 → 1.2.661
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/addon.js +666 -553
- package/dist/addon.mjs +197 -84
- package/dist/ha-export/ha-export.addon.js +77 -71
- package/dist/ha-export/ha-export.addon.mjs +8 -2
- package/dist/{ha-instance-settings-CRvQ5rH6.js → legacy-integration-rows-B_X4VL29.js} +94 -65
- package/dist/{ha-instance-settings-qhCNJbbn.mjs → legacy-integration-rows-Bhvthv-s.mjs} +94 -65
- package/package.json +2 -2
|
@@ -5981,7 +5981,7 @@ var ZodIssueCode = {
|
|
|
5981
5981
|
var ZodFirstPartyTypeKind;
|
|
5982
5982
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5983
5983
|
//#endregion
|
|
5984
|
-
//#region ../types/dist/sleep-
|
|
5984
|
+
//#region ../types/dist/sleep-9TIHFj1w.mjs
|
|
5985
5985
|
/**
|
|
5986
5986
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5987
5987
|
* window to float samples (D455).
|
|
@@ -7935,10 +7935,9 @@ var BaseAddon = class {
|
|
|
7935
7935
|
*
|
|
7936
7936
|
* Override it only when an `instanceMode: multiple` addon's instances differ: an NVR integration
|
|
7937
7937
|
* needs its connection fields, the default integration the addon's own sections. It is the
|
|
7938
|
-
* SHAPE of the form only — the values live
|
|
7939
|
-
* unchanged (`integrations.setSettings` for an account integration).
|
|
7938
|
+
* SHAPE of the form only — the values live on the instance record.
|
|
7940
7939
|
*/
|
|
7941
|
-
async
|
|
7940
|
+
async integrationFormSchema(_instance) {
|
|
7942
7941
|
return null;
|
|
7943
7942
|
}
|
|
7944
7943
|
/**
|
|
@@ -7984,7 +7983,7 @@ var BaseAddon = class {
|
|
|
7984
7983
|
* per-instance schema when it declares one, else its global schema (what they always showed).
|
|
7985
7984
|
*/
|
|
7986
7985
|
async getIntegrationFormSchema(instance, nodeId) {
|
|
7987
|
-
const scoped = await this.
|
|
7986
|
+
const scoped = await this.integrationFormSchema(instance);
|
|
7988
7987
|
if (scoped === null) return this.getGlobalSettings(void 0, void 0, nodeId);
|
|
7989
7988
|
return hydrateSchema(scoped, {}, { inlineSecretsAsViews: true });
|
|
7990
7989
|
}
|
|
@@ -11997,7 +11996,7 @@ object({
|
|
|
11997
11996
|
params: record(string(), union([string(), number()])).optional()
|
|
11998
11997
|
});
|
|
11999
11998
|
//#endregion
|
|
12000
|
-
//#region ../types/dist/composition-
|
|
11999
|
+
//#region ../types/dist/composition-pOHbTzRB.mjs
|
|
12001
12000
|
/**
|
|
12002
12001
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
12003
12002
|
*
|
|
@@ -50856,6 +50855,9 @@ var RunningProposalEvidenceSchema = object({
|
|
|
50856
50855
|
runsFound: number().int().nonnegative(),
|
|
50857
50856
|
pausesFound: number().int().nonnegative(),
|
|
50858
50857
|
longestPauseMs: number().nonnegative(),
|
|
50858
|
+
/** Episodes shorter than ~90 s (an anti-crease pulse, a display waking): never a run, never a pause. */
|
|
50859
|
+
pulsesFound: number().int().nonnegative(),
|
|
50860
|
+
longestPulseMs: number().nonnegative(),
|
|
50859
50861
|
idleFloorW: number(),
|
|
50860
50862
|
noiseCeilingW: number(),
|
|
50861
50863
|
plateauW: number(),
|
|
@@ -56781,11 +56783,7 @@ var CreateIntegrationInputSchema = object({
|
|
|
56781
56783
|
info: record(string(), unknown()).optional(),
|
|
56782
56784
|
/** `stableId` of the discovery candidate the form was seeded from (D984). */
|
|
56783
56785
|
originStableId: string().optional(),
|
|
56784
|
-
settings: record(string(), unknown()).optional()
|
|
56785
|
-
/** Keys of `settings` the form's schema declares secret (by type) — kept in
|
|
56786
|
-
* the keychain, not the table (D787). */
|
|
56787
|
-
secretKeys: array(string()).optional(),
|
|
56788
|
-
skipRestart: boolean().optional()
|
|
56786
|
+
settings: record(string(), unknown()).optional()
|
|
56789
56787
|
});
|
|
56790
56788
|
var UpdateIntegrationInputSchema = object({
|
|
56791
56789
|
id: string(),
|
|
@@ -56806,22 +56804,6 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56806
56804
|
}), method(object({ id: string() }), DeleteIntegrationResultSchema, {
|
|
56807
56805
|
kind: "mutation",
|
|
56808
56806
|
auth: "admin"
|
|
56809
|
-
}), method(object({ id: string() }), record(string(), unknown()), { auth: "admin" }), method(object({
|
|
56810
|
-
id: string(),
|
|
56811
|
-
settings: record(string(), unknown()),
|
|
56812
|
-
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
56813
|
-
secretKeys: array(string()).optional(),
|
|
56814
|
-
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
56815
|
-
skipRestart: boolean().optional()
|
|
56816
|
-
}), object({ success: boolean() }), {
|
|
56817
|
-
kind: "mutation",
|
|
56818
|
-
auth: "admin"
|
|
56819
|
-
}), method(object({ id: string() }), object({
|
|
56820
|
-
rows: number().int().nonnegative(),
|
|
56821
|
-
secrets: number().int().nonnegative()
|
|
56822
|
-
}), {
|
|
56823
|
-
kind: "mutation",
|
|
56824
|
-
auth: "admin"
|
|
56825
56807
|
}), method(_void(), array(AvailableIntegrationTypeSchema), { auth: "admin" }), method(object({
|
|
56826
56808
|
addonId: string(),
|
|
56827
56809
|
settings: record(string(), unknown())
|
|
@@ -59798,6 +59780,27 @@ method(object({}), object({ entries: array(MigrationLedgerEntrySchema) }), { aut
|
|
|
59798
59780
|
}), {
|
|
59799
59781
|
kind: "mutation",
|
|
59800
59782
|
auth: "admin"
|
|
59783
|
+
}), method(object({ integrationId: string().min(1) }), record(string(), unknown()), { auth: "admin" }), method(object({ integrationId: string().min(1) }), object({
|
|
59784
|
+
rows: number().int().nonnegative(),
|
|
59785
|
+
secrets: number().int().nonnegative()
|
|
59786
|
+
}), {
|
|
59787
|
+
kind: "mutation",
|
|
59788
|
+
auth: "admin"
|
|
59789
|
+
}), method(object({
|
|
59790
|
+
integrationId: string().min(1),
|
|
59791
|
+
patch: record(string(), unknown())
|
|
59792
|
+
}), object({ written: boolean() }), {
|
|
59793
|
+
kind: "mutation",
|
|
59794
|
+
auth: "admin"
|
|
59795
|
+
}), method(object({
|
|
59796
|
+
integrationId: string().min(1),
|
|
59797
|
+
keys: array(string().min(1))
|
|
59798
|
+
}), object({
|
|
59799
|
+
present: boolean(),
|
|
59800
|
+
removed: record(string(), unknown())
|
|
59801
|
+
}), {
|
|
59802
|
+
kind: "mutation",
|
|
59803
|
+
auth: "admin"
|
|
59801
59804
|
});
|
|
59802
59805
|
method(object({
|
|
59803
59806
|
sourceUrl: string(),
|
|
@@ -81311,11 +81314,15 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
81311
81314
|
* 1. idle floor F = time-weighted median; noise ceiling N = highest value seen
|
|
81312
81315
|
* near F. A device that is not near one level most of the time has no floor.
|
|
81313
81316
|
* 2. coarse activity = above max(2N, N + 5 W); consecutive stretches are episodes.
|
|
81314
|
-
* 3.
|
|
81315
|
-
*
|
|
81317
|
+
* 3. an episode shorter than `PULSE_MAX_MS` is a PULSE (an anti-crease tumble, a
|
|
81318
|
+
* display waking): it is neither a run nor a pause. Among the remaining
|
|
81319
|
+
* episodes, gaps over `PAUSE_MAX_MS` always separate runs; the rest split in
|
|
81320
|
+
* two by the largest log-scale jump (>= 3x): the short ones are pauses INSIDE
|
|
81321
|
+
* a run (a soak), the long ones separate runs. A stretch under `MIN_RUN_MS`
|
|
81322
|
+
* is no run.
|
|
81316
81323
|
* 4. T = geometric mean of N and the plateau's 10th percentile, snapped to a
|
|
81317
|
-
* grid a person would type; stop dwell covers the longest pause
|
|
81318
|
-
* covers the longest standby blip above T.
|
|
81324
|
+
* grid a person would type; stop dwell covers the longest pause and the
|
|
81325
|
+
* kind's floor; start dwell covers the longest pulse and standby blip above T.
|
|
81319
81326
|
* 5. the numbers are proved by REPLAY through the real `dwell` evaluation: each
|
|
81320
81327
|
* run must hold exactly one true interval and nothing may flap outside.
|
|
81321
81328
|
*/
|
|
@@ -81326,6 +81333,10 @@ var MINUTE_MS$1 = 60 * SECOND_MS;
|
|
|
81326
81333
|
30 * SECOND_MS;
|
|
81327
81334
|
60 * SECOND_MS;
|
|
81328
81335
|
20 * MINUTE_MS$1;
|
|
81336
|
+
90 * SECOND_MS;
|
|
81337
|
+
30 * MINUTE_MS$1;
|
|
81338
|
+
10 * MINUTE_MS$1;
|
|
81339
|
+
DeviceType.Dryer, 3 * MINUTE_MS$1, DeviceType.Dishwasher, 3 * MINUTE_MS$1, DeviceType.Washer, 10 * MINUTE_MS$1;
|
|
81329
81340
|
10 * SECOND_MS;
|
|
81330
81341
|
10 * SECOND_MS;
|
|
81331
81342
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
@@ -86610,13 +86621,6 @@ Object.freeze({
|
|
|
86610
86621
|
access: "create",
|
|
86611
86622
|
role: "admin"
|
|
86612
86623
|
},
|
|
86613
|
-
"integrations.clearSettings": {
|
|
86614
|
-
capName: "integrations",
|
|
86615
|
-
capScope: "system",
|
|
86616
|
-
addonId: null,
|
|
86617
|
-
access: "delete",
|
|
86618
|
-
role: "admin"
|
|
86619
|
-
},
|
|
86620
86624
|
"integrations.create": {
|
|
86621
86625
|
capName: "integrations",
|
|
86622
86626
|
capScope: "system",
|
|
@@ -86652,13 +86656,6 @@ Object.freeze({
|
|
|
86652
86656
|
access: "view",
|
|
86653
86657
|
role: "admin"
|
|
86654
86658
|
},
|
|
86655
|
-
"integrations.getSettings": {
|
|
86656
|
-
capName: "integrations",
|
|
86657
|
-
capScope: "system",
|
|
86658
|
-
addonId: null,
|
|
86659
|
-
access: "view",
|
|
86660
|
-
role: "admin"
|
|
86661
|
-
},
|
|
86662
86659
|
"integrations.list": {
|
|
86663
86660
|
capName: "integrations",
|
|
86664
86661
|
capScope: "system",
|
|
@@ -86666,13 +86663,6 @@ Object.freeze({
|
|
|
86666
86663
|
access: "view",
|
|
86667
86664
|
role: "admin"
|
|
86668
86665
|
},
|
|
86669
|
-
"integrations.setSettings": {
|
|
86670
|
-
capName: "integrations",
|
|
86671
|
-
capScope: "system",
|
|
86672
|
-
addonId: null,
|
|
86673
|
-
access: "create",
|
|
86674
|
-
role: "admin"
|
|
86675
|
-
},
|
|
86676
86666
|
"integrations.testConnection": {
|
|
86677
86667
|
capName: "integrations",
|
|
86678
86668
|
capScope: "system",
|
|
@@ -87667,6 +87657,13 @@ Object.freeze({
|
|
|
87667
87657
|
access: "view",
|
|
87668
87658
|
role: "admin"
|
|
87669
87659
|
},
|
|
87660
|
+
"migrations.clearLegacyIntegrationRows": {
|
|
87661
|
+
capName: "migrations",
|
|
87662
|
+
capScope: "system",
|
|
87663
|
+
addonId: null,
|
|
87664
|
+
access: "delete",
|
|
87665
|
+
role: "admin"
|
|
87666
|
+
},
|
|
87670
87667
|
"migrations.declareOwner": {
|
|
87671
87668
|
capName: "migrations",
|
|
87672
87669
|
capScope: "system",
|
|
@@ -87674,6 +87671,13 @@ Object.freeze({
|
|
|
87674
87671
|
access: "create",
|
|
87675
87672
|
role: "admin"
|
|
87676
87673
|
},
|
|
87674
|
+
"migrations.deleteLegacyIntegrationRowKeys": {
|
|
87675
|
+
capName: "migrations",
|
|
87676
|
+
capScope: "system",
|
|
87677
|
+
addonId: null,
|
|
87678
|
+
access: "delete",
|
|
87679
|
+
role: "admin"
|
|
87680
|
+
},
|
|
87677
87681
|
"migrations.dryRun": {
|
|
87678
87682
|
capName: "migrations",
|
|
87679
87683
|
capScope: "system",
|
|
@@ -87709,6 +87713,20 @@ Object.freeze({
|
|
|
87709
87713
|
access: "create",
|
|
87710
87714
|
role: "admin"
|
|
87711
87715
|
},
|
|
87716
|
+
"migrations.patchLegacyIntegrationRows": {
|
|
87717
|
+
capName: "migrations",
|
|
87718
|
+
capScope: "system",
|
|
87719
|
+
addonId: null,
|
|
87720
|
+
access: "create",
|
|
87721
|
+
role: "admin"
|
|
87722
|
+
},
|
|
87723
|
+
"migrations.readLegacyIntegrationRows": {
|
|
87724
|
+
capName: "migrations",
|
|
87725
|
+
capScope: "system",
|
|
87726
|
+
addonId: null,
|
|
87727
|
+
access: "view",
|
|
87728
|
+
role: "admin"
|
|
87729
|
+
},
|
|
87712
87730
|
"migrations.restorePreMigration": {
|
|
87713
87731
|
capName: "migrations",
|
|
87714
87732
|
capScope: "system",
|
|
@@ -98388,13 +98406,18 @@ var HA_BROKER_KIND = "home-assistant";
|
|
|
98388
98406
|
async function listHomeAssistantBrokers(query) {
|
|
98389
98407
|
return (await query({})).filter((broker) => broker.kind === HA_BROKER_KIND);
|
|
98390
98408
|
}
|
|
98391
|
-
function
|
|
98409
|
+
function refsOfKeys(stored, keys) {
|
|
98410
|
+
const picked = {};
|
|
98411
|
+
for (const key of keys) if (Object.prototype.hasOwnProperty.call(stored, key)) picked[key] = stored[key];
|
|
98412
|
+
return collectSecretMarkerRefs(picked);
|
|
98413
|
+
}
|
|
98414
|
+
function haInstanceSettingsPortsOver(api, secrets = null) {
|
|
98392
98415
|
const listInstances = async () => {
|
|
98393
98416
|
const all = await api.list.query();
|
|
98394
98417
|
const rows = [];
|
|
98395
98418
|
for (const integration of all) {
|
|
98396
98419
|
if (integration.addonId !== "provider-homeassistant") continue;
|
|
98397
|
-
const settings = await api.
|
|
98420
|
+
const settings = await api.readLegacyIntegrationRows.query({ integrationId: integration.id });
|
|
98398
98421
|
const brokerId = settings["brokerId"];
|
|
98399
98422
|
rows.push({
|
|
98400
98423
|
integrationId: integration.id,
|
|
@@ -98404,20 +98427,26 @@ function haInstanceSettingsPortsOver(api) {
|
|
|
98404
98427
|
}
|
|
98405
98428
|
return rows;
|
|
98406
98429
|
};
|
|
98430
|
+
const owns = async (integrationId) => {
|
|
98431
|
+
return (await api.list.query()).some((i) => i.id === integrationId && i.addonId === "provider-homeassistant");
|
|
98432
|
+
};
|
|
98407
98433
|
return {
|
|
98408
98434
|
listInstances,
|
|
98409
98435
|
patchInstanceSettings: async (integrationId, patch) => {
|
|
98410
|
-
if (!
|
|
98411
|
-
|
|
98412
|
-
|
|
98413
|
-
|
|
98414
|
-
|
|
98415
|
-
|
|
98416
|
-
|
|
98417
|
-
|
|
98418
|
-
|
|
98419
|
-
|
|
98420
|
-
return
|
|
98436
|
+
if (!await owns(integrationId)) return false;
|
|
98437
|
+
return (await api.patchLegacyIntegrationRows.mutate({
|
|
98438
|
+
integrationId,
|
|
98439
|
+
patch: { ...patch }
|
|
98440
|
+
})).written;
|
|
98441
|
+
},
|
|
98442
|
+
clearInstanceSettingsKeys: async (integrationId, keys) => {
|
|
98443
|
+
if (!await owns(integrationId)) return false;
|
|
98444
|
+
const refs = refsOfKeys(await api.readLegacyIntegrationRows.query({ integrationId }), keys);
|
|
98445
|
+
if (refs.length > 0 && secrets !== null) await secrets.delete(refs);
|
|
98446
|
+
return (await api.deleteLegacyIntegrationRowKeys.mutate({
|
|
98447
|
+
integrationId,
|
|
98448
|
+
keys
|
|
98449
|
+
})).present;
|
|
98421
98450
|
}
|
|
98422
98451
|
};
|
|
98423
98452
|
}
|
|
@@ -5980,7 +5980,7 @@ var ZodIssueCode = {
|
|
|
5980
5980
|
var ZodFirstPartyTypeKind;
|
|
5981
5981
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5982
5982
|
//#endregion
|
|
5983
|
-
//#region ../types/dist/sleep-
|
|
5983
|
+
//#region ../types/dist/sleep-9TIHFj1w.mjs
|
|
5984
5984
|
/**
|
|
5985
5985
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5986
5986
|
* window to float samples (D455).
|
|
@@ -7934,10 +7934,9 @@ var BaseAddon = class {
|
|
|
7934
7934
|
*
|
|
7935
7935
|
* Override it only when an `instanceMode: multiple` addon's instances differ: an NVR integration
|
|
7936
7936
|
* needs its connection fields, the default integration the addon's own sections. It is the
|
|
7937
|
-
* SHAPE of the form only — the values live
|
|
7938
|
-
* unchanged (`integrations.setSettings` for an account integration).
|
|
7937
|
+
* SHAPE of the form only — the values live on the instance record.
|
|
7939
7938
|
*/
|
|
7940
|
-
async
|
|
7939
|
+
async integrationFormSchema(_instance) {
|
|
7941
7940
|
return null;
|
|
7942
7941
|
}
|
|
7943
7942
|
/**
|
|
@@ -7983,7 +7982,7 @@ var BaseAddon = class {
|
|
|
7983
7982
|
* per-instance schema when it declares one, else its global schema (what they always showed).
|
|
7984
7983
|
*/
|
|
7985
7984
|
async getIntegrationFormSchema(instance, nodeId) {
|
|
7986
|
-
const scoped = await this.
|
|
7985
|
+
const scoped = await this.integrationFormSchema(instance);
|
|
7987
7986
|
if (scoped === null) return this.getGlobalSettings(void 0, void 0, nodeId);
|
|
7988
7987
|
return hydrateSchema(scoped, {}, { inlineSecretsAsViews: true });
|
|
7989
7988
|
}
|
|
@@ -11996,7 +11995,7 @@ object({
|
|
|
11996
11995
|
params: record(string(), union([string(), number()])).optional()
|
|
11997
11996
|
});
|
|
11998
11997
|
//#endregion
|
|
11999
|
-
//#region ../types/dist/composition-
|
|
11998
|
+
//#region ../types/dist/composition-pOHbTzRB.mjs
|
|
12000
11999
|
/**
|
|
12001
12000
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
12002
12001
|
*
|
|
@@ -50855,6 +50854,9 @@ var RunningProposalEvidenceSchema = object({
|
|
|
50855
50854
|
runsFound: number().int().nonnegative(),
|
|
50856
50855
|
pausesFound: number().int().nonnegative(),
|
|
50857
50856
|
longestPauseMs: number().nonnegative(),
|
|
50857
|
+
/** Episodes shorter than ~90 s (an anti-crease pulse, a display waking): never a run, never a pause. */
|
|
50858
|
+
pulsesFound: number().int().nonnegative(),
|
|
50859
|
+
longestPulseMs: number().nonnegative(),
|
|
50858
50860
|
idleFloorW: number(),
|
|
50859
50861
|
noiseCeilingW: number(),
|
|
50860
50862
|
plateauW: number(),
|
|
@@ -56780,11 +56782,7 @@ var CreateIntegrationInputSchema = object({
|
|
|
56780
56782
|
info: record(string(), unknown()).optional(),
|
|
56781
56783
|
/** `stableId` of the discovery candidate the form was seeded from (D984). */
|
|
56782
56784
|
originStableId: string().optional(),
|
|
56783
|
-
settings: record(string(), unknown()).optional()
|
|
56784
|
-
/** Keys of `settings` the form's schema declares secret (by type) — kept in
|
|
56785
|
-
* the keychain, not the table (D787). */
|
|
56786
|
-
secretKeys: array(string()).optional(),
|
|
56787
|
-
skipRestart: boolean().optional()
|
|
56785
|
+
settings: record(string(), unknown()).optional()
|
|
56788
56786
|
});
|
|
56789
56787
|
var UpdateIntegrationInputSchema = object({
|
|
56790
56788
|
id: string(),
|
|
@@ -56805,22 +56803,6 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
56805
56803
|
}), method(object({ id: string() }), DeleteIntegrationResultSchema, {
|
|
56806
56804
|
kind: "mutation",
|
|
56807
56805
|
auth: "admin"
|
|
56808
|
-
}), method(object({ id: string() }), record(string(), unknown()), { auth: "admin" }), method(object({
|
|
56809
|
-
id: string(),
|
|
56810
|
-
settings: record(string(), unknown()),
|
|
56811
|
-
/** Keys the form's schema declares secret (by type) — keychain-stored (D787). */
|
|
56812
|
-
secretKeys: array(string()).optional(),
|
|
56813
|
-
/** The integration's own addon applies the change in-process and asks the hub not to respawn it. */
|
|
56814
|
-
skipRestart: boolean().optional()
|
|
56815
|
-
}), object({ success: boolean() }), {
|
|
56816
|
-
kind: "mutation",
|
|
56817
|
-
auth: "admin"
|
|
56818
|
-
}), method(object({ id: string() }), object({
|
|
56819
|
-
rows: number().int().nonnegative(),
|
|
56820
|
-
secrets: number().int().nonnegative()
|
|
56821
|
-
}), {
|
|
56822
|
-
kind: "mutation",
|
|
56823
|
-
auth: "admin"
|
|
56824
56806
|
}), method(_void(), array(AvailableIntegrationTypeSchema), { auth: "admin" }), method(object({
|
|
56825
56807
|
addonId: string(),
|
|
56826
56808
|
settings: record(string(), unknown())
|
|
@@ -59797,6 +59779,27 @@ method(object({}), object({ entries: array(MigrationLedgerEntrySchema) }), { aut
|
|
|
59797
59779
|
}), {
|
|
59798
59780
|
kind: "mutation",
|
|
59799
59781
|
auth: "admin"
|
|
59782
|
+
}), method(object({ integrationId: string().min(1) }), record(string(), unknown()), { auth: "admin" }), method(object({ integrationId: string().min(1) }), object({
|
|
59783
|
+
rows: number().int().nonnegative(),
|
|
59784
|
+
secrets: number().int().nonnegative()
|
|
59785
|
+
}), {
|
|
59786
|
+
kind: "mutation",
|
|
59787
|
+
auth: "admin"
|
|
59788
|
+
}), method(object({
|
|
59789
|
+
integrationId: string().min(1),
|
|
59790
|
+
patch: record(string(), unknown())
|
|
59791
|
+
}), object({ written: boolean() }), {
|
|
59792
|
+
kind: "mutation",
|
|
59793
|
+
auth: "admin"
|
|
59794
|
+
}), method(object({
|
|
59795
|
+
integrationId: string().min(1),
|
|
59796
|
+
keys: array(string().min(1))
|
|
59797
|
+
}), object({
|
|
59798
|
+
present: boolean(),
|
|
59799
|
+
removed: record(string(), unknown())
|
|
59800
|
+
}), {
|
|
59801
|
+
kind: "mutation",
|
|
59802
|
+
auth: "admin"
|
|
59800
59803
|
});
|
|
59801
59804
|
method(object({
|
|
59802
59805
|
sourceUrl: string(),
|
|
@@ -81310,11 +81313,15 @@ function runningFromMediaPlayer(state, previous, fetchedAt, transitionAt) {
|
|
|
81310
81313
|
* 1. idle floor F = time-weighted median; noise ceiling N = highest value seen
|
|
81311
81314
|
* near F. A device that is not near one level most of the time has no floor.
|
|
81312
81315
|
* 2. coarse activity = above max(2N, N + 5 W); consecutive stretches are episodes.
|
|
81313
|
-
* 3.
|
|
81314
|
-
*
|
|
81316
|
+
* 3. an episode shorter than `PULSE_MAX_MS` is a PULSE (an anti-crease tumble, a
|
|
81317
|
+
* display waking): it is neither a run nor a pause. Among the remaining
|
|
81318
|
+
* episodes, gaps over `PAUSE_MAX_MS` always separate runs; the rest split in
|
|
81319
|
+
* two by the largest log-scale jump (>= 3x): the short ones are pauses INSIDE
|
|
81320
|
+
* a run (a soak), the long ones separate runs. A stretch under `MIN_RUN_MS`
|
|
81321
|
+
* is no run.
|
|
81315
81322
|
* 4. T = geometric mean of N and the plateau's 10th percentile, snapped to a
|
|
81316
|
-
* grid a person would type; stop dwell covers the longest pause
|
|
81317
|
-
* covers the longest standby blip above T.
|
|
81323
|
+
* grid a person would type; stop dwell covers the longest pause and the
|
|
81324
|
+
* kind's floor; start dwell covers the longest pulse and standby blip above T.
|
|
81318
81325
|
* 5. the numbers are proved by REPLAY through the real `dwell` evaluation: each
|
|
81319
81326
|
* run must hold exactly one true interval and nothing may flap outside.
|
|
81320
81327
|
*/
|
|
@@ -81325,6 +81332,10 @@ var MINUTE_MS$1 = 60 * SECOND_MS;
|
|
|
81325
81332
|
30 * SECOND_MS;
|
|
81326
81333
|
60 * SECOND_MS;
|
|
81327
81334
|
20 * MINUTE_MS$1;
|
|
81335
|
+
90 * SECOND_MS;
|
|
81336
|
+
30 * MINUTE_MS$1;
|
|
81337
|
+
10 * MINUTE_MS$1;
|
|
81338
|
+
DeviceType.Dryer, 3 * MINUTE_MS$1, DeviceType.Dishwasher, 3 * MINUTE_MS$1, DeviceType.Washer, 10 * MINUTE_MS$1;
|
|
81328
81339
|
10 * SECOND_MS;
|
|
81329
81340
|
10 * SECOND_MS;
|
|
81330
81341
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
@@ -86609,13 +86620,6 @@ Object.freeze({
|
|
|
86609
86620
|
access: "create",
|
|
86610
86621
|
role: "admin"
|
|
86611
86622
|
},
|
|
86612
|
-
"integrations.clearSettings": {
|
|
86613
|
-
capName: "integrations",
|
|
86614
|
-
capScope: "system",
|
|
86615
|
-
addonId: null,
|
|
86616
|
-
access: "delete",
|
|
86617
|
-
role: "admin"
|
|
86618
|
-
},
|
|
86619
86623
|
"integrations.create": {
|
|
86620
86624
|
capName: "integrations",
|
|
86621
86625
|
capScope: "system",
|
|
@@ -86651,13 +86655,6 @@ Object.freeze({
|
|
|
86651
86655
|
access: "view",
|
|
86652
86656
|
role: "admin"
|
|
86653
86657
|
},
|
|
86654
|
-
"integrations.getSettings": {
|
|
86655
|
-
capName: "integrations",
|
|
86656
|
-
capScope: "system",
|
|
86657
|
-
addonId: null,
|
|
86658
|
-
access: "view",
|
|
86659
|
-
role: "admin"
|
|
86660
|
-
},
|
|
86661
86658
|
"integrations.list": {
|
|
86662
86659
|
capName: "integrations",
|
|
86663
86660
|
capScope: "system",
|
|
@@ -86665,13 +86662,6 @@ Object.freeze({
|
|
|
86665
86662
|
access: "view",
|
|
86666
86663
|
role: "admin"
|
|
86667
86664
|
},
|
|
86668
|
-
"integrations.setSettings": {
|
|
86669
|
-
capName: "integrations",
|
|
86670
|
-
capScope: "system",
|
|
86671
|
-
addonId: null,
|
|
86672
|
-
access: "create",
|
|
86673
|
-
role: "admin"
|
|
86674
|
-
},
|
|
86675
86665
|
"integrations.testConnection": {
|
|
86676
86666
|
capName: "integrations",
|
|
86677
86667
|
capScope: "system",
|
|
@@ -87666,6 +87656,13 @@ Object.freeze({
|
|
|
87666
87656
|
access: "view",
|
|
87667
87657
|
role: "admin"
|
|
87668
87658
|
},
|
|
87659
|
+
"migrations.clearLegacyIntegrationRows": {
|
|
87660
|
+
capName: "migrations",
|
|
87661
|
+
capScope: "system",
|
|
87662
|
+
addonId: null,
|
|
87663
|
+
access: "delete",
|
|
87664
|
+
role: "admin"
|
|
87665
|
+
},
|
|
87669
87666
|
"migrations.declareOwner": {
|
|
87670
87667
|
capName: "migrations",
|
|
87671
87668
|
capScope: "system",
|
|
@@ -87673,6 +87670,13 @@ Object.freeze({
|
|
|
87673
87670
|
access: "create",
|
|
87674
87671
|
role: "admin"
|
|
87675
87672
|
},
|
|
87673
|
+
"migrations.deleteLegacyIntegrationRowKeys": {
|
|
87674
|
+
capName: "migrations",
|
|
87675
|
+
capScope: "system",
|
|
87676
|
+
addonId: null,
|
|
87677
|
+
access: "delete",
|
|
87678
|
+
role: "admin"
|
|
87679
|
+
},
|
|
87676
87680
|
"migrations.dryRun": {
|
|
87677
87681
|
capName: "migrations",
|
|
87678
87682
|
capScope: "system",
|
|
@@ -87708,6 +87712,20 @@ Object.freeze({
|
|
|
87708
87712
|
access: "create",
|
|
87709
87713
|
role: "admin"
|
|
87710
87714
|
},
|
|
87715
|
+
"migrations.patchLegacyIntegrationRows": {
|
|
87716
|
+
capName: "migrations",
|
|
87717
|
+
capScope: "system",
|
|
87718
|
+
addonId: null,
|
|
87719
|
+
access: "create",
|
|
87720
|
+
role: "admin"
|
|
87721
|
+
},
|
|
87722
|
+
"migrations.readLegacyIntegrationRows": {
|
|
87723
|
+
capName: "migrations",
|
|
87724
|
+
capScope: "system",
|
|
87725
|
+
addonId: null,
|
|
87726
|
+
access: "view",
|
|
87727
|
+
role: "admin"
|
|
87728
|
+
},
|
|
87711
87729
|
"migrations.restorePreMigration": {
|
|
87712
87730
|
capName: "migrations",
|
|
87713
87731
|
capScope: "system",
|
|
@@ -98387,13 +98405,18 @@ var HA_BROKER_KIND = "home-assistant";
|
|
|
98387
98405
|
async function listHomeAssistantBrokers(query) {
|
|
98388
98406
|
return (await query({})).filter((broker) => broker.kind === HA_BROKER_KIND);
|
|
98389
98407
|
}
|
|
98390
|
-
function
|
|
98408
|
+
function refsOfKeys(stored, keys) {
|
|
98409
|
+
const picked = {};
|
|
98410
|
+
for (const key of keys) if (Object.prototype.hasOwnProperty.call(stored, key)) picked[key] = stored[key];
|
|
98411
|
+
return collectSecretMarkerRefs(picked);
|
|
98412
|
+
}
|
|
98413
|
+
function haInstanceSettingsPortsOver(api, secrets = null) {
|
|
98391
98414
|
const listInstances = async () => {
|
|
98392
98415
|
const all = await api.list.query();
|
|
98393
98416
|
const rows = [];
|
|
98394
98417
|
for (const integration of all) {
|
|
98395
98418
|
if (integration.addonId !== "provider-homeassistant") continue;
|
|
98396
|
-
const settings = await api.
|
|
98419
|
+
const settings = await api.readLegacyIntegrationRows.query({ integrationId: integration.id });
|
|
98397
98420
|
const brokerId = settings["brokerId"];
|
|
98398
98421
|
rows.push({
|
|
98399
98422
|
integrationId: integration.id,
|
|
@@ -98403,20 +98426,26 @@ function haInstanceSettingsPortsOver(api) {
|
|
|
98403
98426
|
}
|
|
98404
98427
|
return rows;
|
|
98405
98428
|
};
|
|
98429
|
+
const owns = async (integrationId) => {
|
|
98430
|
+
return (await api.list.query()).some((i) => i.id === integrationId && i.addonId === "provider-homeassistant");
|
|
98431
|
+
};
|
|
98406
98432
|
return {
|
|
98407
98433
|
listInstances,
|
|
98408
98434
|
patchInstanceSettings: async (integrationId, patch) => {
|
|
98409
|
-
if (!
|
|
98410
|
-
|
|
98411
|
-
|
|
98412
|
-
|
|
98413
|
-
|
|
98414
|
-
|
|
98415
|
-
|
|
98416
|
-
|
|
98417
|
-
|
|
98418
|
-
|
|
98419
|
-
return
|
|
98435
|
+
if (!await owns(integrationId)) return false;
|
|
98436
|
+
return (await api.patchLegacyIntegrationRows.mutate({
|
|
98437
|
+
integrationId,
|
|
98438
|
+
patch: { ...patch }
|
|
98439
|
+
})).written;
|
|
98440
|
+
},
|
|
98441
|
+
clearInstanceSettingsKeys: async (integrationId, keys) => {
|
|
98442
|
+
if (!await owns(integrationId)) return false;
|
|
98443
|
+
const refs = refsOfKeys(await api.readLegacyIntegrationRows.query({ integrationId }), keys);
|
|
98444
|
+
if (refs.length > 0 && secrets !== null) await secrets.delete(refs);
|
|
98445
|
+
return (await api.deleteLegacyIntegrationRowKeys.mutate({
|
|
98446
|
+
integrationId,
|
|
98447
|
+
keys
|
|
98448
|
+
})).present;
|
|
98420
98449
|
}
|
|
98421
98450
|
};
|
|
98422
98451
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-homeassistant",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.661",
|
|
4
4
|
"description": "Home Assistant device provider addon for CamStack",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"description": "Device provider (import) + native entity export (push). Two addons, one bundle, separate processes."
|
|
138
138
|
},
|
|
139
139
|
"requires": {
|
|
140
|
-
"server": ">=1.2.
|
|
140
|
+
"server": ">=1.2.770"
|
|
141
141
|
}
|
|
142
142
|
},
|
|
143
143
|
"files": [
|