@camstack/addon-provider-homeassistant 1.2.625 → 1.2.627
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 +268 -119
- package/dist/addon.mjs +268 -119
- package/dist/{dist-DvZEnx9C.mjs → dist-BFnk4bwH.mjs} +1314 -497
- package/dist/{dist-oNUlRdur.js → dist-CRwUHjY7.js} +1349 -496
- package/dist/ha-export/ha-export.addon.js +30 -19
- package/dist/ha-export/ha-export.addon.mjs +30 -19
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
//#endregion
|
|
27
|
-
const require_dist = require("../dist-
|
|
27
|
+
const require_dist = require("../dist-CRwUHjY7.js");
|
|
28
28
|
let node_crypto = require("node:crypto");
|
|
29
29
|
require("node:zlib");
|
|
30
30
|
let node_fs = require("node:fs");
|
|
@@ -731,12 +731,6 @@ var STATUS_UNKNOWN = "unknown";
|
|
|
731
731
|
function consumableEntity(key, facet) {
|
|
732
732
|
return `${CONSUMABLE_PREFIX}_${toSlug(key)}_${facet}`;
|
|
733
733
|
}
|
|
734
|
-
/** Home Assistant's own duration units; a cycle count is a plain count. */
|
|
735
|
-
var REMAINING_UNIT = {
|
|
736
|
-
days: "d",
|
|
737
|
-
hours: "h",
|
|
738
|
-
cycles: "cycles"
|
|
739
|
-
};
|
|
740
734
|
/**
|
|
741
735
|
* The item's form (the capability's own derivation, `consumableFormOf`): the one
|
|
742
736
|
* the provider declared when it is a form the capability knows, else the one its
|
|
@@ -829,7 +823,7 @@ function consumableEntities(item) {
|
|
|
829
823
|
entityCategory: "diagnostic"
|
|
830
824
|
});
|
|
831
825
|
if (item.remaining !== void 0) {
|
|
832
|
-
const isDuration = item.remaining.
|
|
826
|
+
const isDuration = item.remaining.kind === "duration";
|
|
833
827
|
out.push({
|
|
834
828
|
...base,
|
|
835
829
|
facet: "remaining",
|
|
@@ -837,7 +831,7 @@ function consumableEntities(item) {
|
|
|
837
831
|
uniqueSuffix: unique("remaining"),
|
|
838
832
|
platform: "sensor",
|
|
839
833
|
label: `${item.label} remaining`,
|
|
840
|
-
unit:
|
|
834
|
+
...isDuration ? { unit: "s" } : {},
|
|
841
835
|
stateClass: "measurement",
|
|
842
836
|
...isDuration ? { deviceClass: "duration" } : {},
|
|
843
837
|
icon: isDuration ? "mdi:timer-sand" : "mdi:counter",
|
|
@@ -3184,7 +3178,7 @@ mireds: {
|
|
|
3184
3178
|
platform: "sensor",
|
|
3185
3179
|
field: "desiccantLeftDays",
|
|
3186
3180
|
label: "Desiccant remaining",
|
|
3187
|
-
unit: "
|
|
3181
|
+
unit: "s",
|
|
3188
3182
|
entityCategory: "diagnostic",
|
|
3189
3183
|
enabledByDefault: false
|
|
3190
3184
|
},
|
|
@@ -3198,11 +3192,8 @@ mireds: {
|
|
|
3198
3192
|
}
|
|
3199
3193
|
},
|
|
3200
3194
|
/**
|
|
3201
|
-
*
|
|
3202
|
-
*
|
|
3203
|
-
* `unit_of_measurement` can be honest for a provider reporting °F.
|
|
3204
|
-
* Declaring one anyway is how a dashboard comes to say 71 °C. Humidity
|
|
3205
|
-
* is the exception: a percentage is a percentage.
|
|
3195
|
+
* Weather numbers are stored in the quantity base (°C, hPa, m/s). The
|
|
3196
|
+
* export advertises those symbols. A Fahrenheit dashboard converts at read.
|
|
3206
3197
|
*/
|
|
3207
3198
|
weather: {
|
|
3208
3199
|
platform: "sensor",
|
|
@@ -3213,6 +3204,8 @@ mireds: {
|
|
|
3213
3204
|
platform: "sensor",
|
|
3214
3205
|
field: "temperature",
|
|
3215
3206
|
label: "Temperature",
|
|
3207
|
+
unit: "°C",
|
|
3208
|
+
deviceClass: "temperature",
|
|
3216
3209
|
icon: "mdi:thermometer"
|
|
3217
3210
|
},
|
|
3218
3211
|
humidity: {
|
|
@@ -3226,6 +3219,8 @@ mireds: {
|
|
|
3226
3219
|
platform: "sensor",
|
|
3227
3220
|
field: "pressure",
|
|
3228
3221
|
label: "Pressure",
|
|
3222
|
+
unit: "hPa",
|
|
3223
|
+
deviceClass: "pressure",
|
|
3229
3224
|
icon: "mdi:gauge",
|
|
3230
3225
|
enabledByDefault: false
|
|
3231
3226
|
},
|
|
@@ -3233,6 +3228,8 @@ mireds: {
|
|
|
3233
3228
|
platform: "sensor",
|
|
3234
3229
|
field: "windSpeed",
|
|
3235
3230
|
label: "Wind speed",
|
|
3231
|
+
unit: "m/s",
|
|
3232
|
+
deviceClass: "wind_speed",
|
|
3236
3233
|
icon: "mdi:weather-windy",
|
|
3237
3234
|
enabledByDefault: false
|
|
3238
3235
|
},
|
|
@@ -3443,7 +3440,7 @@ function readFiniteNumber(slice, field) {
|
|
|
3443
3440
|
* builds with nothing to choose from — so an empty list falls back to a
|
|
3444
3441
|
* read-only sensor rather than a dead control.
|
|
3445
3442
|
*/
|
|
3446
|
-
function controlEntitySpecs(slice) {
|
|
3443
|
+
function controlEntitySpecs(slice, quantity) {
|
|
3447
3444
|
const kind = typeof slice?.["kind"] === "string" ? slice["kind"] : null;
|
|
3448
3445
|
const primary = derivedEntityId("control");
|
|
3449
3446
|
const kindExtra = {
|
|
@@ -3468,7 +3465,7 @@ function controlEntitySpecs(slice) {
|
|
|
3468
3465
|
const min = readFiniteNumber(slice, "min") ?? PERCENT_RANGE.min;
|
|
3469
3466
|
const max = readFiniteNumber(slice, "max") ?? PERCENT_RANGE.max;
|
|
3470
3467
|
const step = readFiniteNumber(slice, "step") ?? PERCENT_RANGE.step;
|
|
3471
|
-
const unit =
|
|
3468
|
+
const unit = quantity === void 0 ? void 0 : require_dist.baseUnitOf(quantity);
|
|
3472
3469
|
if (min < max && step > 0) return [{
|
|
3473
3470
|
entity: primary,
|
|
3474
3471
|
platform: "number",
|
|
@@ -3491,6 +3488,10 @@ function controlEntitySpecs(slice) {
|
|
|
3491
3488
|
}, kindExtra];
|
|
3492
3489
|
}
|
|
3493
3490
|
var CAPS_NOT_EXPORTED = [
|
|
3491
|
+
{
|
|
3492
|
+
cap: "group-status",
|
|
3493
|
+
reason: "Bookkeeping for a helper group (D944): how many members were included, excluded, or named. The value an operator automates on is the output capability (the temperature, the motion, the watts). These counts are session-only, have no history, and would publish a second entity that never means the reading."
|
|
3494
|
+
},
|
|
3494
3495
|
{
|
|
3495
3496
|
cap: "recording-onboard",
|
|
3496
3497
|
reason: "An EDITOR of the CAMERA’s own recorder: a weekly schedule of windows per trigger, plus the facts about the card it writes to. The schedule is a document an operator authors, not a reading — an entity would publish 168 slots as a state and nothing in Home Assistant could act on it. The storage side is a reading, but it belongs to the camera’s own health rather than to this cap’s editor surface, and publishing capacity here would put the same number in two places the day a health cap carries it. ONE thing here is arguably a real binary sensor: `recordingToNowhere` — scheduled to record with no usable card. It is deliberately NOT exported yet, because exporting half a cap needs the split decided first, and the two cameras it fires on today are already a danger banner and a WARN."
|
|
@@ -3738,7 +3739,15 @@ function buildDerivedPlan(device, options = UNNEGOTIATED_PLAN_OPTIONS) {
|
|
|
3738
3739
|
* row stays the projector + writable-route authority.
|
|
3739
3740
|
*/
|
|
3740
3741
|
if (cap === "control") {
|
|
3741
|
-
specs.push(...controlEntitySpecs(device.capSlices?.["control"]).map((spec) => degradeUnsupported(spec, options)));
|
|
3742
|
+
specs.push(...controlEntitySpecs(device.capSlices?.["control"], device.readingQuantity).map((spec) => degradeUnsupported(spec, options)));
|
|
3743
|
+
continue;
|
|
3744
|
+
}
|
|
3745
|
+
if (cap === "numeric-sensor") {
|
|
3746
|
+
const unit = device.readingQuantity === void 0 ? void 0 : require_dist.baseUnitOf(device.readingQuantity);
|
|
3747
|
+
specs.push(...capEntitySpecs(cap).map((spec) => degradeUnsupported(unit === void 0 ? spec : {
|
|
3748
|
+
...spec,
|
|
3749
|
+
unit
|
|
3750
|
+
}, options)));
|
|
3742
3751
|
continue;
|
|
3743
3752
|
}
|
|
3744
3753
|
const mapping = CAP_ENTITY_MAP[cap];
|
|
@@ -7963,6 +7972,7 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
7963
7972
|
if (items.held) heldBack = true;
|
|
7964
7973
|
const manufacturer = readString(device.metadata ?? {}, "manufacturer");
|
|
7965
7974
|
const model = readString(device.metadata ?? {}, "model");
|
|
7975
|
+
const readingQuantity = device.sourceInfo?.quantity;
|
|
7966
7976
|
return {
|
|
7967
7977
|
device: {
|
|
7968
7978
|
id: device.id,
|
|
@@ -7984,7 +7994,8 @@ var HaExportAddon = class extends require_dist.BaseAddon {
|
|
|
7984
7994
|
* `CatalogDevice.capSlices`.
|
|
7985
7995
|
*/
|
|
7986
7996
|
capSlices: snapshot,
|
|
7987
|
-
itemEntities: items.entities
|
|
7997
|
+
itemEntities: items.entities,
|
|
7998
|
+
...require_dist.isReadingQuantity(readingQuantity) ? { readingQuantity } : {}
|
|
7988
7999
|
},
|
|
7989
8000
|
heldBack
|
|
7990
8001
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $t as unknown, D as buildAddonRouteProvider, F as consumableFormOf, H as deviceExportCapability, Ht as nodePin, I as consumableKindOf, It as baseUnitOf, Pt as BaseAddon, Vt as isReadingQuantity, Wt as array, Yt as object, Zt as string, _ as addonRoutesCapability, a as COCO_TO_MACRO, c as ConsumableItemSchema, d as FanDirectionSchema, f as HvacModeSchema, i as CAMERA_SWITCH_ORDER, l as ConsumableStatusSchema, o as CameraSwitchIdSchema, ot as oauthIntegrationCapability, p as MediaPlayerRepeatSchema, s as ConsumableFormSchema, t as AlarmArmModeSchema, tn as EventCategory } from "../dist-BFnk4bwH.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
import "node:zlib";
|
|
4
4
|
import "node:fs";
|
|
@@ -703,12 +703,6 @@ var STATUS_UNKNOWN = "unknown";
|
|
|
703
703
|
function consumableEntity(key, facet) {
|
|
704
704
|
return `${CONSUMABLE_PREFIX}_${toSlug(key)}_${facet}`;
|
|
705
705
|
}
|
|
706
|
-
/** Home Assistant's own duration units; a cycle count is a plain count. */
|
|
707
|
-
var REMAINING_UNIT = {
|
|
708
|
-
days: "d",
|
|
709
|
-
hours: "h",
|
|
710
|
-
cycles: "cycles"
|
|
711
|
-
};
|
|
712
706
|
/**
|
|
713
707
|
* The item's form (the capability's own derivation, `consumableFormOf`): the one
|
|
714
708
|
* the provider declared when it is a form the capability knows, else the one its
|
|
@@ -794,7 +788,7 @@ function consumableEntities(item) {
|
|
|
794
788
|
entityCategory: "diagnostic"
|
|
795
789
|
});
|
|
796
790
|
if (item.remaining !== void 0) {
|
|
797
|
-
const isDuration = item.remaining.
|
|
791
|
+
const isDuration = item.remaining.kind === "duration";
|
|
798
792
|
out.push({
|
|
799
793
|
...base,
|
|
800
794
|
facet: "remaining",
|
|
@@ -802,7 +796,7 @@ function consumableEntities(item) {
|
|
|
802
796
|
uniqueSuffix: unique("remaining"),
|
|
803
797
|
platform: "sensor",
|
|
804
798
|
label: `${item.label} remaining`,
|
|
805
|
-
unit:
|
|
799
|
+
...isDuration ? { unit: "s" } : {},
|
|
806
800
|
stateClass: "measurement",
|
|
807
801
|
...isDuration ? { deviceClass: "duration" } : {},
|
|
808
802
|
icon: isDuration ? "mdi:timer-sand" : "mdi:counter",
|
|
@@ -3149,7 +3143,7 @@ mireds: {
|
|
|
3149
3143
|
platform: "sensor",
|
|
3150
3144
|
field: "desiccantLeftDays",
|
|
3151
3145
|
label: "Desiccant remaining",
|
|
3152
|
-
unit: "
|
|
3146
|
+
unit: "s",
|
|
3153
3147
|
entityCategory: "diagnostic",
|
|
3154
3148
|
enabledByDefault: false
|
|
3155
3149
|
},
|
|
@@ -3163,11 +3157,8 @@ mireds: {
|
|
|
3163
3157
|
}
|
|
3164
3158
|
},
|
|
3165
3159
|
/**
|
|
3166
|
-
*
|
|
3167
|
-
*
|
|
3168
|
-
* `unit_of_measurement` can be honest for a provider reporting °F.
|
|
3169
|
-
* Declaring one anyway is how a dashboard comes to say 71 °C. Humidity
|
|
3170
|
-
* is the exception: a percentage is a percentage.
|
|
3160
|
+
* Weather numbers are stored in the quantity base (°C, hPa, m/s). The
|
|
3161
|
+
* export advertises those symbols. A Fahrenheit dashboard converts at read.
|
|
3171
3162
|
*/
|
|
3172
3163
|
weather: {
|
|
3173
3164
|
platform: "sensor",
|
|
@@ -3178,6 +3169,8 @@ mireds: {
|
|
|
3178
3169
|
platform: "sensor",
|
|
3179
3170
|
field: "temperature",
|
|
3180
3171
|
label: "Temperature",
|
|
3172
|
+
unit: "°C",
|
|
3173
|
+
deviceClass: "temperature",
|
|
3181
3174
|
icon: "mdi:thermometer"
|
|
3182
3175
|
},
|
|
3183
3176
|
humidity: {
|
|
@@ -3191,6 +3184,8 @@ mireds: {
|
|
|
3191
3184
|
platform: "sensor",
|
|
3192
3185
|
field: "pressure",
|
|
3193
3186
|
label: "Pressure",
|
|
3187
|
+
unit: "hPa",
|
|
3188
|
+
deviceClass: "pressure",
|
|
3194
3189
|
icon: "mdi:gauge",
|
|
3195
3190
|
enabledByDefault: false
|
|
3196
3191
|
},
|
|
@@ -3198,6 +3193,8 @@ mireds: {
|
|
|
3198
3193
|
platform: "sensor",
|
|
3199
3194
|
field: "windSpeed",
|
|
3200
3195
|
label: "Wind speed",
|
|
3196
|
+
unit: "m/s",
|
|
3197
|
+
deviceClass: "wind_speed",
|
|
3201
3198
|
icon: "mdi:weather-windy",
|
|
3202
3199
|
enabledByDefault: false
|
|
3203
3200
|
},
|
|
@@ -3408,7 +3405,7 @@ function readFiniteNumber(slice, field) {
|
|
|
3408
3405
|
* builds with nothing to choose from — so an empty list falls back to a
|
|
3409
3406
|
* read-only sensor rather than a dead control.
|
|
3410
3407
|
*/
|
|
3411
|
-
function controlEntitySpecs(slice) {
|
|
3408
|
+
function controlEntitySpecs(slice, quantity) {
|
|
3412
3409
|
const kind = typeof slice?.["kind"] === "string" ? slice["kind"] : null;
|
|
3413
3410
|
const primary = derivedEntityId("control");
|
|
3414
3411
|
const kindExtra = {
|
|
@@ -3433,7 +3430,7 @@ function controlEntitySpecs(slice) {
|
|
|
3433
3430
|
const min = readFiniteNumber(slice, "min") ?? PERCENT_RANGE.min;
|
|
3434
3431
|
const max = readFiniteNumber(slice, "max") ?? PERCENT_RANGE.max;
|
|
3435
3432
|
const step = readFiniteNumber(slice, "step") ?? PERCENT_RANGE.step;
|
|
3436
|
-
const unit =
|
|
3433
|
+
const unit = quantity === void 0 ? void 0 : baseUnitOf(quantity);
|
|
3437
3434
|
if (min < max && step > 0) return [{
|
|
3438
3435
|
entity: primary,
|
|
3439
3436
|
platform: "number",
|
|
@@ -3456,6 +3453,10 @@ function controlEntitySpecs(slice) {
|
|
|
3456
3453
|
}, kindExtra];
|
|
3457
3454
|
}
|
|
3458
3455
|
var CAPS_NOT_EXPORTED = [
|
|
3456
|
+
{
|
|
3457
|
+
cap: "group-status",
|
|
3458
|
+
reason: "Bookkeeping for a helper group (D944): how many members were included, excluded, or named. The value an operator automates on is the output capability (the temperature, the motion, the watts). These counts are session-only, have no history, and would publish a second entity that never means the reading."
|
|
3459
|
+
},
|
|
3459
3460
|
{
|
|
3460
3461
|
cap: "recording-onboard",
|
|
3461
3462
|
reason: "An EDITOR of the CAMERA’s own recorder: a weekly schedule of windows per trigger, plus the facts about the card it writes to. The schedule is a document an operator authors, not a reading — an entity would publish 168 slots as a state and nothing in Home Assistant could act on it. The storage side is a reading, but it belongs to the camera’s own health rather than to this cap’s editor surface, and publishing capacity here would put the same number in two places the day a health cap carries it. ONE thing here is arguably a real binary sensor: `recordingToNowhere` — scheduled to record with no usable card. It is deliberately NOT exported yet, because exporting half a cap needs the split decided first, and the two cameras it fires on today are already a danger banner and a WARN."
|
|
@@ -3703,7 +3704,15 @@ function buildDerivedPlan(device, options = UNNEGOTIATED_PLAN_OPTIONS) {
|
|
|
3703
3704
|
* row stays the projector + writable-route authority.
|
|
3704
3705
|
*/
|
|
3705
3706
|
if (cap === "control") {
|
|
3706
|
-
specs.push(...controlEntitySpecs(device.capSlices?.["control"]).map((spec) => degradeUnsupported(spec, options)));
|
|
3707
|
+
specs.push(...controlEntitySpecs(device.capSlices?.["control"], device.readingQuantity).map((spec) => degradeUnsupported(spec, options)));
|
|
3708
|
+
continue;
|
|
3709
|
+
}
|
|
3710
|
+
if (cap === "numeric-sensor") {
|
|
3711
|
+
const unit = device.readingQuantity === void 0 ? void 0 : baseUnitOf(device.readingQuantity);
|
|
3712
|
+
specs.push(...capEntitySpecs(cap).map((spec) => degradeUnsupported(unit === void 0 ? spec : {
|
|
3713
|
+
...spec,
|
|
3714
|
+
unit
|
|
3715
|
+
}, options)));
|
|
3707
3716
|
continue;
|
|
3708
3717
|
}
|
|
3709
3718
|
const mapping = CAP_ENTITY_MAP[cap];
|
|
@@ -7928,6 +7937,7 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
7928
7937
|
if (items.held) heldBack = true;
|
|
7929
7938
|
const manufacturer = readString(device.metadata ?? {}, "manufacturer");
|
|
7930
7939
|
const model = readString(device.metadata ?? {}, "model");
|
|
7940
|
+
const readingQuantity = device.sourceInfo?.quantity;
|
|
7931
7941
|
return {
|
|
7932
7942
|
device: {
|
|
7933
7943
|
id: device.id,
|
|
@@ -7949,7 +7959,8 @@ var HaExportAddon = class extends BaseAddon {
|
|
|
7949
7959
|
* `CatalogDevice.capSlices`.
|
|
7950
7960
|
*/
|
|
7951
7961
|
capSlices: snapshot,
|
|
7952
|
-
itemEntities: items.entities
|
|
7962
|
+
itemEntities: items.entities,
|
|
7963
|
+
...isReadingQuantity(readingQuantity) ? { readingQuantity } : {}
|
|
7953
7964
|
},
|
|
7954
7965
|
heldBack
|
|
7955
7966
|
};
|