@camstack/types 1.2.419 → 1.2.420
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/client.d.ts +1 -1
- package/dist/client.js +157 -0
- package/dist/client.mjs +157 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
* value this entry does not export — a missing name here is `undefined` at
|
|
15
15
|
* runtime, not a build error.
|
|
16
16
|
*/
|
|
17
|
-
export { APPLE_SA_TO_MACRO, AUDIO_MACRO_LABELS, AlarmArmModeSchema, CLIP_BROKER_PACED_RATES, COCO_TO_MACRO, CamProfileSchema, ICON_CATEGORIES, ICON_ENTRIES, ICON_KEYS, ICON_VIEWER_MODULES, IconKeySchema, LOCATION_ICON_FALLBACK, DEFINITIVE_DEVICE_REFUSALS, DEVICE_CERT_RENEW_WINDOW_DAYS, DEVICE_DEFINITIVE_REFUSALS_BEFORE_DELETE, DEVICE_REFRESH_REFUSAL_PREFIX, DEVICE_CERT_SIGNATURE, DEVICE_SIGNATURE_MESSAGE_VERSION, DEFAULT_TIMELAPSE_PREVIEW_TEXT, DeviceType, EVENTFUL_CAP_NAMES, EVENT_KIND_BY_CAP, EVENT_TAXONOMY, MACRO_LABELS, NC_ALARM_DELAY_MAX_SEC, NC_ALARM_SENSORS_MAX, NC_ALARM_SYSTEM_EVENT_KINDS, NC_ALARM_TRIGGERED_MAX_SEC, NC_BATTERY_CONSUMABLE_SYSTEM_EVENT_KINDS, NC_CAMERA_SCOPE_CAP_NAME, NC_CONSUMABLE_LOW_PERCENT_DEFAULT, NC_CONSUMABLE_LOW_PERCENT_MAX, NC_GROUPING_DEFAULT_SEC, NC_GROUPING_MAX_SEC, NC_GROUPING_MIN_SEC, NC_RULE_EDITOR_SECTION_ORDER, NC_RULE_KIND_SPECS, NC_SENSOR_TRANSITION_UNSUPPORTED_REASON, NC_SYSTEM_EVENT_FAMILY_FILTERS, NC_SYSTEM_EVENT_CLASS_SPECS, NC_SYSTEM_EVENT_KIND_GROUP_SPECS, NC_SYSTEM_EVENT_SUMMARY_FAMILIES, NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS, NC_TEMPLATE_VARS, NcAlarmConfigSchema, NcAlarmSensorsSchema, NcAlarmSettingsPatchSchema, NcHistoryEntrySchema, NcRuleLastRunsSchema, NodeDirectorySchema, RECORDING_EXPORT_MAX_READ_BYTES, RETRAIN_REVIEW_ADJUSTED_IOU, RETRAIN_REVIEW_MATCH_IOU, RETRAIN_REVIEW_STATUSES, RETRAIN_REVISION_CONFLICT, SystemMirror, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleSchema, YAMNET_TO_MACRO, alarmDeviceBlocksArming, alarmDeviceSecureOnArm, alarmPatchLanded, canonicalIconKey, buildDeviceEnrollmentLink, buildDeviceSignatureMessage, deviceRefusalFromMessage, isDefinitiveDeviceRefusal, classifyRetrainReview, conditionVisibleForKind, createSystemProxy, droppedConditionsForKind, iconCategoryLabel, iconEntry, iconsInCategory, isIconKey, isHeldBackTemplateVar, isSystemRuleKind, kindsForDiscriminator, locationIconKey, knownValues, nodePickerItems, parseDeviceEnrollmentLink, packagePickerItems, pickerForCondition, pickerForRuleClasses, parseRetrainRevisionConflict, resolveIconKey, resolveModeDelays, retrainBoxIou, retrainRevisionConflictMessage, ruleDeviceCompatCapNames, ruleEditorSectionsForKind, ruleGroupingApplies, ruleKindOf, ruleKindSpec, ruleSeedForSection, searchIcons, sensorTransitionNeverFires, sensorTransitionOffered, stateLabel, summarizeReview, systemEventClassesFor, systemEventClassKinds, systemEventDeliveryProblems, systemEventFilterAppliesToAnyKind, systemEventKindsOfFamily, systemFamilyOfKind, templateCarriesSummary, templateVarDeliveryApplies, templateVarKindApplies, templateVarSystemEventApplies, buildSubjectPath, isDrawableSubjectPath, projectSubjectPath, subjectPathSampleFromBox, subjectPathSvgPoints, expandSystemEventClasses, withSystemEventClasses, bundledCamstack, paintHex, paletteResultSchema, } from './index.js';
|
|
17
|
+
export { APPLE_SA_TO_MACRO, AUDIO_MACRO_LABELS, AlarmArmModeSchema, CLIP_BROKER_PACED_RATES, COCO_TO_MACRO, CamProfileSchema, ICON_CATEGORIES, ICON_ENTRIES, ICON_KEYS, ICON_VIEWER_MODULES, IconKeySchema, LOCATION_ICON_FALLBACK, DEFINITIVE_DEVICE_REFUSALS, DEVICE_CERT_RENEW_WINDOW_DAYS, DEVICE_DEFINITIVE_REFUSALS_BEFORE_DELETE, DEVICE_REFRESH_REFUSAL_PREFIX, DEVICE_CERT_SIGNATURE, DEVICE_SIGNATURE_MESSAGE_VERSION, DEFAULT_TIMELAPSE_PREVIEW_TEXT, DeviceType, EVENTFUL_CAP_NAMES, EVENT_KIND_BY_CAP, EVENT_TAXONOMY, MACRO_LABELS, NC_ALARM_DELAY_MAX_SEC, NC_ALARM_SENSORS_MAX, NC_ALARM_SYSTEM_EVENT_KINDS, NC_ALARM_TRIGGERED_MAX_SEC, NC_BATTERY_CONSUMABLE_SYSTEM_EVENT_KINDS, NC_CAMERA_SCOPE_CAP_NAME, NC_CONSUMABLE_LOW_PERCENT_DEFAULT, NC_CONSUMABLE_LOW_PERCENT_MAX, NC_GROUPING_DEFAULT_SEC, NC_GROUPING_MAX_SEC, NC_GROUPING_MIN_SEC, NC_RULE_EDITOR_SECTION_ORDER, NC_RULE_KIND_SPECS, NC_SENSOR_TRANSITION_UNSUPPORTED_REASON, NC_SYSTEM_EVENT_FAMILY_FILTERS, NC_SYSTEM_EVENT_CLASS_SPECS, NC_SYSTEM_EVENT_KIND_GROUP_SPECS, NC_SYSTEM_EVENT_SUMMARY_FAMILIES, NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS, NC_TEMPLATE_VARS, NcAlarmConfigSchema, NcAlarmSensorsSchema, NcAlarmSettingsPatchSchema, NcHistoryEntrySchema, NcRuleLastRunsSchema, NodeDirectorySchema, RECORDING_EXPORT_MAX_READ_BYTES, RETRAIN_REVIEW_ADJUSTED_IOU, RETRAIN_REVIEW_MATCH_IOU, RETRAIN_REVIEW_STATUSES, RETRAIN_REVISION_CONFLICT, SystemMirror, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleSchema, YAMNET_TO_MACRO, alarmDeviceBlocksArming, alarmDeviceSecureOnArm, alarmPatchLanded, canonicalIconKey, buildDeviceEnrollmentLink, buildDeviceSignatureMessage, deviceRefusalFromMessage, isDefinitiveDeviceRefusal, classifyRetrainReview, conditionVisibleForKind, createSystemProxy, droppedConditionsForKind, iconCategoryLabel, iconEntry, iconsInCategory, isIconKey, isHeldBackTemplateVar, isSystemRuleKind, kindsForDiscriminator, locationIconKey, knownValues, nodePickerItems, parseDeviceEnrollmentLink, packagePickerItems, pickerForCondition, pickerForRuleClasses, parseRetrainRevisionConflict, resolveIconKey, resolveModeDelays, retrainBoxIou, retrainRevisionConflictMessage, ruleDeviceCompatCapNames, ruleEditorSectionsForKind, ruleGroupingApplies, ruleKindOf, ruleKindSpec, ruleSeedForSection, searchIcons, sensorTransitionNeverFires, sensorTransitionOffered, stateLabel, summarizeReview, systemEventClassesFor, systemEventClassKinds, systemEventDeliveryProblems, systemEventFilterAppliesToAnyKind, systemEventKindsOfFamily, systemFamilyOfKind, templateCarriesSummary, templateVarDeliveryApplies, templateVarKindApplies, templateVarSystemEventApplies, buildSubjectPath, isDrawableSubjectPath, projectSubjectPath, subjectPathSampleFromBox, subjectPathSvgPoints, expandSystemEventClasses, withSystemEventClasses, bundledCamstack, paintHex, paletteResultSchema, resolveContainerPrimaryChild, } from './index.js';
|
|
18
18
|
export type { PaletteReady, PaletteResult, PaletteEntryId, PalettePresetId } from './index.js';
|
package/dist/client.js
CHANGED
|
@@ -26236,6 +26236,162 @@ method(zod.z.object({
|
|
|
26236
26236
|
auth: "protected"
|
|
26237
26237
|
});
|
|
26238
26238
|
//#endregion
|
|
26239
|
+
//#region src/device/container-primary-child.ts
|
|
26240
|
+
/**
|
|
26241
|
+
* WHICH child a container stands for — one definition, for every consumer.
|
|
26242
|
+
*
|
|
26243
|
+
* A CONTAINER device has no controllable surface of its own: it groups entity
|
|
26244
|
+
* children (a Gree air-conditioner grouping a climate child plus light, x-fan
|
|
26245
|
+
* and health switches). Everything that has to show or act on a container has
|
|
26246
|
+
* to answer the same question — which child IS the container — and until now
|
|
26247
|
+
* three places answered it separately:
|
|
26248
|
+
*
|
|
26249
|
+
* - `ui-library/device-controls/primary-child.ts` (admin-ui rendering)
|
|
26250
|
+
* - `addon-provider-homeassistant` PARENT_TYPE_PRIORITY (adoption)
|
|
26251
|
+
* - the viewer's own `container-primary.ts` (linked-devices panel)
|
|
26252
|
+
*
|
|
26253
|
+
* Each carried the same list and a comment asking the others to stay in sync.
|
|
26254
|
+
* This is that list, in the one package all of them already depend on.
|
|
26255
|
+
*
|
|
26256
|
+
* `ui-library` and the server's linked-devices expansion IMPORT it. Two
|
|
26257
|
+
* consumers cannot, and keep a checked copy instead: the viewer resolves
|
|
26258
|
+
* `@camstack/types` from its own `node_modules` (an installed release, where a
|
|
26259
|
+
* newly added export simply is not there), and the Home Assistant provider
|
|
26260
|
+
* expresses the same precedence over the `DeviceType` enum because it answers
|
|
26261
|
+
* a different question from the same ordering. `scripts/check-container-
|
|
26262
|
+
* priority-in-sync.ts` fails the build when either drifts — the comment that
|
|
26263
|
+
* used to ask for this could not.
|
|
26264
|
+
*
|
|
26265
|
+
* The rule has two halves and the ORDER matters: an operator's explicit pick
|
|
26266
|
+
* wins outright, and only in its absence does type priority decide. The pick is
|
|
26267
|
+
* keyed on the child's re-sync-stable `entityId`, not its numeric id, so it
|
|
26268
|
+
* survives a re-sync that reallocates ids.
|
|
26269
|
+
*/
|
|
26270
|
+
/**
|
|
26271
|
+
* Type priority, most→least "primary". An actuator (climate / lock / cover / …)
|
|
26272
|
+
* outranks a bare `switch` so a container's defining child wins over its
|
|
26273
|
+
* auxiliary switches. Unknown or absent types sort after every entry.
|
|
26274
|
+
*
|
|
26275
|
+
* NB: `siren` deliberately sits BELOW `switch` — it is a switch-family
|
|
26276
|
+
* actuator, and a camera's siren must not out-rank the thing the container is.
|
|
26277
|
+
*
|
|
26278
|
+
* These strings are matched against a child's `DeviceType` VALUE, so they must
|
|
26279
|
+
* equal the enum's string values.
|
|
26280
|
+
*/
|
|
26281
|
+
var CONTAINER_CHILD_PRIORITY = [
|
|
26282
|
+
"media-player",
|
|
26283
|
+
"alarm-panel",
|
|
26284
|
+
"thermostat",
|
|
26285
|
+
"climate",
|
|
26286
|
+
"humidifier",
|
|
26287
|
+
"water-heater",
|
|
26288
|
+
"lock",
|
|
26289
|
+
"cover",
|
|
26290
|
+
"valve",
|
|
26291
|
+
"fan",
|
|
26292
|
+
"vacuum",
|
|
26293
|
+
"lawn-mower",
|
|
26294
|
+
"dishwasher",
|
|
26295
|
+
"light",
|
|
26296
|
+
"switch",
|
|
26297
|
+
"siren",
|
|
26298
|
+
"button",
|
|
26299
|
+
"control",
|
|
26300
|
+
"notifier",
|
|
26301
|
+
"script",
|
|
26302
|
+
"automation",
|
|
26303
|
+
"update",
|
|
26304
|
+
"presence",
|
|
26305
|
+
"weather",
|
|
26306
|
+
"image",
|
|
26307
|
+
"sensor"
|
|
26308
|
+
];
|
|
26309
|
+
/**
|
|
26310
|
+
* Roles that say what a container IS, most→least defining. Consulted BEFORE
|
|
26311
|
+
* type priority, because `DeviceType` cannot tell them apart: Home Assistant
|
|
26312
|
+
* maps a door contact, a battery level, a temperature reading and a "last seen"
|
|
26313
|
+
* timestamp all to `DeviceType.Sensor`. Measured on container 4127 — children
|
|
26314
|
+
* `battery-sensor`, `temperature-sensor`, `datetime-sensor`, `contact-sensor`
|
|
26315
|
+
* and a role-less `button` — the type list ranked `button` above `sensor` and
|
|
26316
|
+
* the container stood for its "Identifica" button instead of the door contact
|
|
26317
|
+
* it is named after.
|
|
26318
|
+
*
|
|
26319
|
+
* Only STATE-DEFINING roles belong here. A diagnostic reading (battery,
|
|
26320
|
+
* temperature, humidity, signal, last-seen) is never what a container is, so
|
|
26321
|
+
* they are deliberately absent and fall through to type priority.
|
|
26322
|
+
*/
|
|
26323
|
+
var CONTAINER_CHILD_ROLE_PRIORITY = [
|
|
26324
|
+
"contact-sensor",
|
|
26325
|
+
"motion-sensor",
|
|
26326
|
+
"occupancy-sensor",
|
|
26327
|
+
"smoke-sensor",
|
|
26328
|
+
"co-sensor",
|
|
26329
|
+
"gas-sensor",
|
|
26330
|
+
"leak-sensor",
|
|
26331
|
+
"vibration-sensor",
|
|
26332
|
+
"tamper-sensor",
|
|
26333
|
+
"sound-sensor"
|
|
26334
|
+
];
|
|
26335
|
+
/**
|
|
26336
|
+
* NOT in the list, deliberately: `binary-sensor` and `binary-helper`. They are
|
|
26337
|
+
* GENERIC — they say "this reports a boolean", not what the container is — and
|
|
26338
|
+
* ranking them above type priority is a live regression, not a hypothetical:
|
|
26339
|
+
* container 1837 holds a real `lock` (features `['lock-open']`) alongside a
|
|
26340
|
+
* child named "Actuator" whose only role is `binary-sensor`, and the generic
|
|
26341
|
+
* role beat the lock. A role earns a place here by naming a SUBJECT (a contact,
|
|
26342
|
+
* a leak, smoke), never by naming a datatype.
|
|
26343
|
+
*/
|
|
26344
|
+
function roleRank(role) {
|
|
26345
|
+
if (role === void 0) return CONTAINER_CHILD_ROLE_PRIORITY.length;
|
|
26346
|
+
const i = CONTAINER_CHILD_ROLE_PRIORITY.indexOf(role);
|
|
26347
|
+
return i === -1 ? CONTAINER_CHILD_ROLE_PRIORITY.length : i;
|
|
26348
|
+
}
|
|
26349
|
+
function rank(type) {
|
|
26350
|
+
const i = CONTAINER_CHILD_PRIORITY.indexOf(type);
|
|
26351
|
+
return i === -1 ? CONTAINER_CHILD_PRIORITY.length : i;
|
|
26352
|
+
}
|
|
26353
|
+
/**
|
|
26354
|
+
* The child a container stands for: the operator's pick when it still exists,
|
|
26355
|
+
* else the highest-priority type. `null` for a childless container — a caller
|
|
26356
|
+
* must decide what an empty container means for it, rather than being handed a
|
|
26357
|
+
* child that is not there.
|
|
26358
|
+
*/
|
|
26359
|
+
/**
|
|
26360
|
+
* Two names for the same thing, compared the way an integration writes them.
|
|
26361
|
+
*
|
|
26362
|
+
* An exact case-insensitive match was not enough, and the failure was total
|
|
26363
|
+
* rather than marginal. An ESPHome shutter arrives as a container named
|
|
26364
|
+
* `Tapparella-Kitchen` whose children include the COVER, named `Tapparella
|
|
26365
|
+
* kitchen`, and a device-presence entity carrying the slug verbatim,
|
|
26366
|
+
* `tapparella-kitchen`. The slug matched the container exactly and the cover
|
|
26367
|
+
* did not, so the namesake tie-break handed the container to a connectivity
|
|
26368
|
+
* indicator — and the viewer's accessory panel, which correctly shows only
|
|
26369
|
+
* children with an actuating control, then rendered NOTHING. The operator saw
|
|
26370
|
+
* no shutters at all on kitchen, studio and both porch cameras (2026-09-22).
|
|
26371
|
+
*
|
|
26372
|
+
* `Markise` was the control case that proved the mechanism: there the cover
|
|
26373
|
+
* really is called exactly like its container, so it won and appeared.
|
|
26374
|
+
*
|
|
26375
|
+
* Separators are therefore normalised — `-`, `_` and whitespace are the same
|
|
26376
|
+
* character for this comparison, and runs of them collapse. The two candidates
|
|
26377
|
+
* then tie on the namesake and the decision falls through to `rank(type)`,
|
|
26378
|
+
* where `cover` is eighth and a `presence` entity is not listed at all. The
|
|
26379
|
+
* criterion keeps doing its job for a container whose child IS the namesake;
|
|
26380
|
+
* it stops being decided by which integration used a hyphen.
|
|
26381
|
+
*/
|
|
26382
|
+
function sameName(childName, containerName) {
|
|
26383
|
+
const flatten = (v) => v.toLowerCase().replace(/[-_\s]+/g, " ").trim();
|
|
26384
|
+
return flatten(childName) === flatten(containerName);
|
|
26385
|
+
}
|
|
26386
|
+
function resolveContainerPrimaryChild(children, overrideEntityId, containerName) {
|
|
26387
|
+
if (overrideEntityId !== void 0 && overrideEntityId !== null) {
|
|
26388
|
+
const picked = children.find((c) => c.stableId === overrideEntityId) ?? children.find((c) => c.entityId !== void 0 && c.entityId === overrideEntityId);
|
|
26389
|
+
if (picked !== void 0) return picked;
|
|
26390
|
+
}
|
|
26391
|
+
const namesake = (c) => containerName !== void 0 && containerName.length > 0 && c.name !== void 0 && sameName(c.name, containerName) ? 0 : 1;
|
|
26392
|
+
return [...children].toSorted((a, b) => roleRank(a.role) - roleRank(b.role) || namesake(a) - namesake(b) || rank(a.type) - rank(b.type))[0] ?? null;
|
|
26393
|
+
}
|
|
26394
|
+
//#endregion
|
|
26239
26395
|
//#region src/device/device-state-handle.ts
|
|
26240
26396
|
var DEVICE_STATE_EVENT_CATEGORY = "device.state-changed";
|
|
26241
26397
|
/**
|
|
@@ -32331,6 +32487,7 @@ exports.parseRetrainRevisionConflict = parseRetrainRevisionConflict;
|
|
|
32331
32487
|
exports.pickerForCondition = pickerForCondition;
|
|
32332
32488
|
exports.pickerForRuleClasses = pickerForRuleClasses;
|
|
32333
32489
|
exports.projectSubjectPath = projectSubjectPath;
|
|
32490
|
+
exports.resolveContainerPrimaryChild = resolveContainerPrimaryChild;
|
|
32334
32491
|
exports.resolveIconKey = resolveIconKey;
|
|
32335
32492
|
exports.resolveModeDelays = resolveModeDelays;
|
|
32336
32493
|
exports.retrainBoxIou = retrainBoxIou;
|
package/dist/client.mjs
CHANGED
|
@@ -26235,6 +26235,162 @@ method(z.object({
|
|
|
26235
26235
|
auth: "protected"
|
|
26236
26236
|
});
|
|
26237
26237
|
//#endregion
|
|
26238
|
+
//#region src/device/container-primary-child.ts
|
|
26239
|
+
/**
|
|
26240
|
+
* WHICH child a container stands for — one definition, for every consumer.
|
|
26241
|
+
*
|
|
26242
|
+
* A CONTAINER device has no controllable surface of its own: it groups entity
|
|
26243
|
+
* children (a Gree air-conditioner grouping a climate child plus light, x-fan
|
|
26244
|
+
* and health switches). Everything that has to show or act on a container has
|
|
26245
|
+
* to answer the same question — which child IS the container — and until now
|
|
26246
|
+
* three places answered it separately:
|
|
26247
|
+
*
|
|
26248
|
+
* - `ui-library/device-controls/primary-child.ts` (admin-ui rendering)
|
|
26249
|
+
* - `addon-provider-homeassistant` PARENT_TYPE_PRIORITY (adoption)
|
|
26250
|
+
* - the viewer's own `container-primary.ts` (linked-devices panel)
|
|
26251
|
+
*
|
|
26252
|
+
* Each carried the same list and a comment asking the others to stay in sync.
|
|
26253
|
+
* This is that list, in the one package all of them already depend on.
|
|
26254
|
+
*
|
|
26255
|
+
* `ui-library` and the server's linked-devices expansion IMPORT it. Two
|
|
26256
|
+
* consumers cannot, and keep a checked copy instead: the viewer resolves
|
|
26257
|
+
* `@camstack/types` from its own `node_modules` (an installed release, where a
|
|
26258
|
+
* newly added export simply is not there), and the Home Assistant provider
|
|
26259
|
+
* expresses the same precedence over the `DeviceType` enum because it answers
|
|
26260
|
+
* a different question from the same ordering. `scripts/check-container-
|
|
26261
|
+
* priority-in-sync.ts` fails the build when either drifts — the comment that
|
|
26262
|
+
* used to ask for this could not.
|
|
26263
|
+
*
|
|
26264
|
+
* The rule has two halves and the ORDER matters: an operator's explicit pick
|
|
26265
|
+
* wins outright, and only in its absence does type priority decide. The pick is
|
|
26266
|
+
* keyed on the child's re-sync-stable `entityId`, not its numeric id, so it
|
|
26267
|
+
* survives a re-sync that reallocates ids.
|
|
26268
|
+
*/
|
|
26269
|
+
/**
|
|
26270
|
+
* Type priority, most→least "primary". An actuator (climate / lock / cover / …)
|
|
26271
|
+
* outranks a bare `switch` so a container's defining child wins over its
|
|
26272
|
+
* auxiliary switches. Unknown or absent types sort after every entry.
|
|
26273
|
+
*
|
|
26274
|
+
* NB: `siren` deliberately sits BELOW `switch` — it is a switch-family
|
|
26275
|
+
* actuator, and a camera's siren must not out-rank the thing the container is.
|
|
26276
|
+
*
|
|
26277
|
+
* These strings are matched against a child's `DeviceType` VALUE, so they must
|
|
26278
|
+
* equal the enum's string values.
|
|
26279
|
+
*/
|
|
26280
|
+
var CONTAINER_CHILD_PRIORITY = [
|
|
26281
|
+
"media-player",
|
|
26282
|
+
"alarm-panel",
|
|
26283
|
+
"thermostat",
|
|
26284
|
+
"climate",
|
|
26285
|
+
"humidifier",
|
|
26286
|
+
"water-heater",
|
|
26287
|
+
"lock",
|
|
26288
|
+
"cover",
|
|
26289
|
+
"valve",
|
|
26290
|
+
"fan",
|
|
26291
|
+
"vacuum",
|
|
26292
|
+
"lawn-mower",
|
|
26293
|
+
"dishwasher",
|
|
26294
|
+
"light",
|
|
26295
|
+
"switch",
|
|
26296
|
+
"siren",
|
|
26297
|
+
"button",
|
|
26298
|
+
"control",
|
|
26299
|
+
"notifier",
|
|
26300
|
+
"script",
|
|
26301
|
+
"automation",
|
|
26302
|
+
"update",
|
|
26303
|
+
"presence",
|
|
26304
|
+
"weather",
|
|
26305
|
+
"image",
|
|
26306
|
+
"sensor"
|
|
26307
|
+
];
|
|
26308
|
+
/**
|
|
26309
|
+
* Roles that say what a container IS, most→least defining. Consulted BEFORE
|
|
26310
|
+
* type priority, because `DeviceType` cannot tell them apart: Home Assistant
|
|
26311
|
+
* maps a door contact, a battery level, a temperature reading and a "last seen"
|
|
26312
|
+
* timestamp all to `DeviceType.Sensor`. Measured on container 4127 — children
|
|
26313
|
+
* `battery-sensor`, `temperature-sensor`, `datetime-sensor`, `contact-sensor`
|
|
26314
|
+
* and a role-less `button` — the type list ranked `button` above `sensor` and
|
|
26315
|
+
* the container stood for its "Identifica" button instead of the door contact
|
|
26316
|
+
* it is named after.
|
|
26317
|
+
*
|
|
26318
|
+
* Only STATE-DEFINING roles belong here. A diagnostic reading (battery,
|
|
26319
|
+
* temperature, humidity, signal, last-seen) is never what a container is, so
|
|
26320
|
+
* they are deliberately absent and fall through to type priority.
|
|
26321
|
+
*/
|
|
26322
|
+
var CONTAINER_CHILD_ROLE_PRIORITY = [
|
|
26323
|
+
"contact-sensor",
|
|
26324
|
+
"motion-sensor",
|
|
26325
|
+
"occupancy-sensor",
|
|
26326
|
+
"smoke-sensor",
|
|
26327
|
+
"co-sensor",
|
|
26328
|
+
"gas-sensor",
|
|
26329
|
+
"leak-sensor",
|
|
26330
|
+
"vibration-sensor",
|
|
26331
|
+
"tamper-sensor",
|
|
26332
|
+
"sound-sensor"
|
|
26333
|
+
];
|
|
26334
|
+
/**
|
|
26335
|
+
* NOT in the list, deliberately: `binary-sensor` and `binary-helper`. They are
|
|
26336
|
+
* GENERIC — they say "this reports a boolean", not what the container is — and
|
|
26337
|
+
* ranking them above type priority is a live regression, not a hypothetical:
|
|
26338
|
+
* container 1837 holds a real `lock` (features `['lock-open']`) alongside a
|
|
26339
|
+
* child named "Actuator" whose only role is `binary-sensor`, and the generic
|
|
26340
|
+
* role beat the lock. A role earns a place here by naming a SUBJECT (a contact,
|
|
26341
|
+
* a leak, smoke), never by naming a datatype.
|
|
26342
|
+
*/
|
|
26343
|
+
function roleRank(role) {
|
|
26344
|
+
if (role === void 0) return CONTAINER_CHILD_ROLE_PRIORITY.length;
|
|
26345
|
+
const i = CONTAINER_CHILD_ROLE_PRIORITY.indexOf(role);
|
|
26346
|
+
return i === -1 ? CONTAINER_CHILD_ROLE_PRIORITY.length : i;
|
|
26347
|
+
}
|
|
26348
|
+
function rank(type) {
|
|
26349
|
+
const i = CONTAINER_CHILD_PRIORITY.indexOf(type);
|
|
26350
|
+
return i === -1 ? CONTAINER_CHILD_PRIORITY.length : i;
|
|
26351
|
+
}
|
|
26352
|
+
/**
|
|
26353
|
+
* The child a container stands for: the operator's pick when it still exists,
|
|
26354
|
+
* else the highest-priority type. `null` for a childless container — a caller
|
|
26355
|
+
* must decide what an empty container means for it, rather than being handed a
|
|
26356
|
+
* child that is not there.
|
|
26357
|
+
*/
|
|
26358
|
+
/**
|
|
26359
|
+
* Two names for the same thing, compared the way an integration writes them.
|
|
26360
|
+
*
|
|
26361
|
+
* An exact case-insensitive match was not enough, and the failure was total
|
|
26362
|
+
* rather than marginal. An ESPHome shutter arrives as a container named
|
|
26363
|
+
* `Tapparella-Kitchen` whose children include the COVER, named `Tapparella
|
|
26364
|
+
* kitchen`, and a device-presence entity carrying the slug verbatim,
|
|
26365
|
+
* `tapparella-kitchen`. The slug matched the container exactly and the cover
|
|
26366
|
+
* did not, so the namesake tie-break handed the container to a connectivity
|
|
26367
|
+
* indicator — and the viewer's accessory panel, which correctly shows only
|
|
26368
|
+
* children with an actuating control, then rendered NOTHING. The operator saw
|
|
26369
|
+
* no shutters at all on kitchen, studio and both porch cameras (2026-09-22).
|
|
26370
|
+
*
|
|
26371
|
+
* `Markise` was the control case that proved the mechanism: there the cover
|
|
26372
|
+
* really is called exactly like its container, so it won and appeared.
|
|
26373
|
+
*
|
|
26374
|
+
* Separators are therefore normalised — `-`, `_` and whitespace are the same
|
|
26375
|
+
* character for this comparison, and runs of them collapse. The two candidates
|
|
26376
|
+
* then tie on the namesake and the decision falls through to `rank(type)`,
|
|
26377
|
+
* where `cover` is eighth and a `presence` entity is not listed at all. The
|
|
26378
|
+
* criterion keeps doing its job for a container whose child IS the namesake;
|
|
26379
|
+
* it stops being decided by which integration used a hyphen.
|
|
26380
|
+
*/
|
|
26381
|
+
function sameName(childName, containerName) {
|
|
26382
|
+
const flatten = (v) => v.toLowerCase().replace(/[-_\s]+/g, " ").trim();
|
|
26383
|
+
return flatten(childName) === flatten(containerName);
|
|
26384
|
+
}
|
|
26385
|
+
function resolveContainerPrimaryChild(children, overrideEntityId, containerName) {
|
|
26386
|
+
if (overrideEntityId !== void 0 && overrideEntityId !== null) {
|
|
26387
|
+
const picked = children.find((c) => c.stableId === overrideEntityId) ?? children.find((c) => c.entityId !== void 0 && c.entityId === overrideEntityId);
|
|
26388
|
+
if (picked !== void 0) return picked;
|
|
26389
|
+
}
|
|
26390
|
+
const namesake = (c) => containerName !== void 0 && containerName.length > 0 && c.name !== void 0 && sameName(c.name, containerName) ? 0 : 1;
|
|
26391
|
+
return [...children].toSorted((a, b) => roleRank(a.role) - roleRank(b.role) || namesake(a) - namesake(b) || rank(a.type) - rank(b.type))[0] ?? null;
|
|
26392
|
+
}
|
|
26393
|
+
//#endregion
|
|
26238
26394
|
//#region src/device/device-state-handle.ts
|
|
26239
26395
|
var DEVICE_STATE_EVENT_CATEGORY = "device.state-changed";
|
|
26240
26396
|
/**
|
|
@@ -32237,4 +32393,4 @@ var TimelapseRuleSchema = TimelapseRuleInputSchema.extend({
|
|
|
32237
32393
|
updatedAt: z.number()
|
|
32238
32394
|
});
|
|
32239
32395
|
//#endregion
|
|
32240
|
-
export { APPLE_SA_TO_MACRO, AUDIO_MACRO_LABELS, AlarmArmModeSchema, CLIP_BROKER_PACED_RATES, COCO_TO_MACRO, CamProfileSchema, DEFAULT_TIMELAPSE_PREVIEW_TEXT, DEFINITIVE_DEVICE_REFUSALS, DEVICE_CERT_RENEW_WINDOW_DAYS, DEVICE_CERT_SIGNATURE, DEVICE_DEFINITIVE_REFUSALS_BEFORE_DELETE, DEVICE_REFRESH_REFUSAL_PREFIX, DEVICE_SIGNATURE_MESSAGE_VERSION, DeviceType, EVENTFUL_CAP_NAMES, EVENT_KIND_BY_CAP, EVENT_TAXONOMY, ICON_CATEGORIES, ICON_ENTRIES, ICON_KEYS, ICON_VIEWER_MODULES, IconKeySchema, LOCATION_ICON_FALLBACK, MACRO_LABELS, NC_ALARM_DELAY_MAX_SEC, NC_ALARM_SENSORS_MAX, NC_ALARM_SYSTEM_EVENT_KINDS, NC_ALARM_TRIGGERED_MAX_SEC, NC_BATTERY_CONSUMABLE_SYSTEM_EVENT_KINDS, NC_CAMERA_SCOPE_CAP_NAME, NC_CONSUMABLE_LOW_PERCENT_DEFAULT, NC_CONSUMABLE_LOW_PERCENT_MAX, NC_GROUPING_DEFAULT_SEC, NC_GROUPING_MAX_SEC, NC_GROUPING_MIN_SEC, NC_RULE_EDITOR_SECTION_ORDER, NC_RULE_KIND_SPECS, NC_SENSOR_TRANSITION_UNSUPPORTED_REASON, NC_SYSTEM_EVENT_CLASS_SPECS, NC_SYSTEM_EVENT_FAMILY_FILTERS, NC_SYSTEM_EVENT_KIND_GROUP_SPECS, NC_SYSTEM_EVENT_SUMMARY_FAMILIES, NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS, NC_TEMPLATE_VARS, NcAlarmConfigSchema, NcAlarmSensorsSchema, NcAlarmSettingsPatchSchema, NcHistoryEntrySchema, NcRuleLastRunsSchema, NodeDirectorySchema, RECORDING_EXPORT_MAX_READ_BYTES, RETRAIN_REVIEW_ADJUSTED_IOU, RETRAIN_REVIEW_MATCH_IOU, RETRAIN_REVIEW_STATUSES, RETRAIN_REVISION_CONFLICT, SystemMirror, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleSchema, YAMNET_TO_MACRO, alarmDeviceBlocksArming, alarmDeviceSecureOnArm, alarmPatchLanded, buildDeviceEnrollmentLink, buildDeviceSignatureMessage, buildSubjectPath, bundledCamstack, canonicalIconKey, classifyRetrainReview, conditionVisibleForKind, createSystemProxy, deviceRefusalFromMessage, droppedConditionsForKind, expandSystemEventClasses, iconCategoryLabel, iconEntry, iconsInCategory, isDefinitiveDeviceRefusal, isDrawableSubjectPath, isHeldBackTemplateVar, isIconKey, isSystemRuleKind, kindsForDiscriminator, knownValues, locationIconKey, nodePickerItems, packagePickerItems, paintHex, paletteResultSchema, parseDeviceEnrollmentLink, parseRetrainRevisionConflict, pickerForCondition, pickerForRuleClasses, projectSubjectPath, resolveIconKey, resolveModeDelays, retrainBoxIou, retrainRevisionConflictMessage, ruleDeviceCompatCapNames, ruleEditorSectionsForKind, ruleGroupingApplies, ruleKindOf, ruleKindSpec, ruleSeedForSection, searchIcons, sensorTransitionNeverFires, sensorTransitionOffered, stateLabel, subjectPathSampleFromBox, subjectPathSvgPoints, summarizeReview, systemEventClassKinds, systemEventClassesFor, systemEventDeliveryProblems, systemEventFilterAppliesToAnyKind, systemEventKindsOfFamily, systemFamilyOfKind, templateCarriesSummary, templateVarDeliveryApplies, templateVarKindApplies, templateVarSystemEventApplies, withSystemEventClasses };
|
|
32396
|
+
export { APPLE_SA_TO_MACRO, AUDIO_MACRO_LABELS, AlarmArmModeSchema, CLIP_BROKER_PACED_RATES, COCO_TO_MACRO, CamProfileSchema, DEFAULT_TIMELAPSE_PREVIEW_TEXT, DEFINITIVE_DEVICE_REFUSALS, DEVICE_CERT_RENEW_WINDOW_DAYS, DEVICE_CERT_SIGNATURE, DEVICE_DEFINITIVE_REFUSALS_BEFORE_DELETE, DEVICE_REFRESH_REFUSAL_PREFIX, DEVICE_SIGNATURE_MESSAGE_VERSION, DeviceType, EVENTFUL_CAP_NAMES, EVENT_KIND_BY_CAP, EVENT_TAXONOMY, ICON_CATEGORIES, ICON_ENTRIES, ICON_KEYS, ICON_VIEWER_MODULES, IconKeySchema, LOCATION_ICON_FALLBACK, MACRO_LABELS, NC_ALARM_DELAY_MAX_SEC, NC_ALARM_SENSORS_MAX, NC_ALARM_SYSTEM_EVENT_KINDS, NC_ALARM_TRIGGERED_MAX_SEC, NC_BATTERY_CONSUMABLE_SYSTEM_EVENT_KINDS, NC_CAMERA_SCOPE_CAP_NAME, NC_CONSUMABLE_LOW_PERCENT_DEFAULT, NC_CONSUMABLE_LOW_PERCENT_MAX, NC_GROUPING_DEFAULT_SEC, NC_GROUPING_MAX_SEC, NC_GROUPING_MIN_SEC, NC_RULE_EDITOR_SECTION_ORDER, NC_RULE_KIND_SPECS, NC_SENSOR_TRANSITION_UNSUPPORTED_REASON, NC_SYSTEM_EVENT_CLASS_SPECS, NC_SYSTEM_EVENT_FAMILY_FILTERS, NC_SYSTEM_EVENT_KIND_GROUP_SPECS, NC_SYSTEM_EVENT_SUMMARY_FAMILIES, NC_TEMPLATE_HELD_BACK_SYSTEM_EVENT_KINDS, NC_TEMPLATE_VARS, NcAlarmConfigSchema, NcAlarmSensorsSchema, NcAlarmSettingsPatchSchema, NcHistoryEntrySchema, NcRuleLastRunsSchema, NodeDirectorySchema, RECORDING_EXPORT_MAX_READ_BYTES, RETRAIN_REVIEW_ADJUSTED_IOU, RETRAIN_REVIEW_MATCH_IOU, RETRAIN_REVIEW_STATUSES, RETRAIN_REVISION_CONFLICT, SystemMirror, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleSchema, YAMNET_TO_MACRO, alarmDeviceBlocksArming, alarmDeviceSecureOnArm, alarmPatchLanded, buildDeviceEnrollmentLink, buildDeviceSignatureMessage, buildSubjectPath, bundledCamstack, canonicalIconKey, classifyRetrainReview, conditionVisibleForKind, createSystemProxy, deviceRefusalFromMessage, droppedConditionsForKind, expandSystemEventClasses, iconCategoryLabel, iconEntry, iconsInCategory, isDefinitiveDeviceRefusal, isDrawableSubjectPath, isHeldBackTemplateVar, isIconKey, isSystemRuleKind, kindsForDiscriminator, knownValues, locationIconKey, nodePickerItems, packagePickerItems, paintHex, paletteResultSchema, parseDeviceEnrollmentLink, parseRetrainRevisionConflict, pickerForCondition, pickerForRuleClasses, projectSubjectPath, resolveContainerPrimaryChild, resolveIconKey, resolveModeDelays, retrainBoxIou, retrainRevisionConflictMessage, ruleDeviceCompatCapNames, ruleEditorSectionsForKind, ruleGroupingApplies, ruleKindOf, ruleKindSpec, ruleSeedForSection, searchIcons, sensorTransitionNeverFires, sensorTransitionOffered, stateLabel, subjectPathSampleFromBox, subjectPathSvgPoints, summarizeReview, systemEventClassKinds, systemEventClassesFor, systemEventDeliveryProblems, systemEventFilterAppliesToAnyKind, systemEventKindsOfFamily, systemFamilyOfKind, templateCarriesSummary, templateVarDeliveryApplies, templateVarKindApplies, templateVarSystemEventApplies, withSystemEventClasses };
|