@camstack/addon-provider-ecowitt 0.1.5 → 0.1.6
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 +91 -28
- package/dist/addon.mjs +91 -28
- package/package.json +2 -2
package/dist/addon.js
CHANGED
|
@@ -10082,15 +10082,18 @@ var humiditySensorCapability = {
|
|
|
10082
10082
|
runtimeState: HumiditySensorStatusSchema
|
|
10083
10083
|
};
|
|
10084
10084
|
/**
|
|
10085
|
-
* Image display cap. Models
|
|
10086
|
-
*
|
|
10085
|
+
* Image display cap. Models a single still image exposed by an integration —
|
|
10086
|
+
* a snapshot, a chart, a generated picture, or a robot's cleaning-map render.
|
|
10087
10087
|
*
|
|
10088
|
-
* Read-only: there are no setters. The provider resolves
|
|
10089
|
-
*
|
|
10090
|
-
*
|
|
10091
|
-
*
|
|
10092
|
-
*
|
|
10093
|
-
*
|
|
10088
|
+
* Read-only: there are no setters. The provider resolves whatever upstream
|
|
10089
|
+
* source it has into an ABSOLUTE URL the browser loads directly:
|
|
10090
|
+
* - HA `image.*` entities → the `entity_picture` signed-token path
|
|
10091
|
+
* (token stays in the query string, so no auth header is needed);
|
|
10092
|
+
* - a Dreame/robot map → the cloud/OSS map-image URL (or an addon
|
|
10093
|
+
* data-plane URL serving the rendered map bytes), exposed as its own
|
|
10094
|
+
* Image child device grouped under the robot's container.
|
|
10095
|
+
* The slice carries that URL plus the upstream last-updated timestamp; the
|
|
10096
|
+
* image changes when the source's last-updated marker changes.
|
|
10094
10097
|
*/
|
|
10095
10098
|
var ImageStatusSchema = object({
|
|
10096
10099
|
/** Absolute signed URL the browser loads directly. Null when the
|
|
@@ -10116,18 +10119,47 @@ var imageCapability = {
|
|
|
10116
10119
|
*/
|
|
10117
10120
|
runtimeState: ImageStatusSchema
|
|
10118
10121
|
};
|
|
10122
|
+
/**
|
|
10123
|
+
* Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
|
|
10124
|
+
* with a mowing lifecycle plus a dock action.
|
|
10125
|
+
*
|
|
10126
|
+
* Activity follows HA's canonical lawn-mower lifecycle: `idle` /
|
|
10127
|
+
* `mowing` / `paused` / `docked` / `error`. `batteryLevel` (0..100) is
|
|
10128
|
+
* nullable — some mowers don't report a battery percentage.
|
|
10129
|
+
*
|
|
10130
|
+
* `startMowing` begins a mowing run, `pause` halts it in place, and
|
|
10131
|
+
* `dock` sends the mower back to its charging station.
|
|
10132
|
+
*/
|
|
10133
|
+
var LawnMowerActivitySchema = _enum([
|
|
10134
|
+
"idle",
|
|
10135
|
+
"mowing",
|
|
10136
|
+
"paused",
|
|
10137
|
+
"docked",
|
|
10138
|
+
"error"
|
|
10139
|
+
]);
|
|
10140
|
+
/** Severity of the current device/error code — info (status), warning, error. */
|
|
10141
|
+
var DeviceCodeSeveritySchema = _enum([
|
|
10142
|
+
"info",
|
|
10143
|
+
"warning",
|
|
10144
|
+
"error"
|
|
10145
|
+
]);
|
|
10119
10146
|
var LawnMowerControlStatusSchema = object({
|
|
10120
10147
|
/** Lifecycle activity of the mower. */
|
|
10121
|
-
activity:
|
|
10122
|
-
"idle",
|
|
10123
|
-
"mowing",
|
|
10124
|
-
"paused",
|
|
10125
|
-
"docked",
|
|
10126
|
-
"error"
|
|
10127
|
-
]),
|
|
10148
|
+
activity: LawnMowerActivitySchema,
|
|
10128
10149
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
10129
10150
|
* reading. */
|
|
10130
10151
|
batteryLevel: number().min(0).max(100).nullable(),
|
|
10152
|
+
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
10153
|
+
* task is active / progress is unavailable. */
|
|
10154
|
+
progressPercent: number().min(0).max(100).nullable(),
|
|
10155
|
+
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
10156
|
+
* or null when unknown. */
|
|
10157
|
+
currentCode: number().nullable(),
|
|
10158
|
+
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
10159
|
+
currentCodeLabel: string().nullable(),
|
|
10160
|
+
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
10161
|
+
* attention; `info` is normal status. */
|
|
10162
|
+
severity: DeviceCodeSeveritySchema,
|
|
10131
10163
|
/** Ms epoch when the slice was last updated. */
|
|
10132
10164
|
lastChangedAt: number()
|
|
10133
10165
|
});
|
|
@@ -12353,6 +12385,7 @@ var VacuumStateSchema = _enum([
|
|
|
12353
12385
|
"paused",
|
|
12354
12386
|
"returning",
|
|
12355
12387
|
"docked",
|
|
12388
|
+
"drying",
|
|
12356
12389
|
"error"
|
|
12357
12390
|
]);
|
|
12358
12391
|
/**
|
|
@@ -12391,6 +12424,12 @@ var VacuumControlStatusSchema = object({
|
|
|
12391
12424
|
detergent: TankStatusSchema.nullable(),
|
|
12392
12425
|
/** Dust bin. Null when the hardware has no dust bin. */
|
|
12393
12426
|
dustBin: TankStatusSchema.nullable(),
|
|
12427
|
+
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
12428
|
+
progressPercent: number().min(0).max(100).nullable(),
|
|
12429
|
+
/** Current error code (0 / null = no error). */
|
|
12430
|
+
errorCode: number().nullable(),
|
|
12431
|
+
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
12432
|
+
errorLabel: string().nullable(),
|
|
12394
12433
|
/** Ms epoch when the slice was last updated. */
|
|
12395
12434
|
lastChangedAt: number()
|
|
12396
12435
|
});
|
|
@@ -16906,6 +16945,9 @@ method(object({
|
|
|
16906
16945
|
}), method(ReleaseInputSchema.extend({ addonId: string() }), _void(), {
|
|
16907
16946
|
kind: "mutation",
|
|
16908
16947
|
auth: "admin"
|
|
16948
|
+
}), method(ResyncInputSchema, ResyncResultSchema, {
|
|
16949
|
+
kind: "mutation",
|
|
16950
|
+
auth: "admin"
|
|
16909
16951
|
}), method(object({
|
|
16910
16952
|
deviceId: number(),
|
|
16911
16953
|
key: string(),
|
|
@@ -20668,6 +20710,12 @@ Object.freeze({
|
|
|
20668
20710
|
addonId: null,
|
|
20669
20711
|
access: "create"
|
|
20670
20712
|
},
|
|
20713
|
+
"deviceManager.adoptionResync": {
|
|
20714
|
+
capName: "device-manager",
|
|
20715
|
+
capScope: "system",
|
|
20716
|
+
addonId: null,
|
|
20717
|
+
access: "create"
|
|
20718
|
+
},
|
|
20671
20719
|
"deviceManager.allocateDeviceId": {
|
|
20672
20720
|
capName: "device-manager",
|
|
20673
20721
|
capScope: "system",
|
|
@@ -44576,7 +44624,8 @@ function classifyKey(key) {
|
|
|
44576
44624
|
const hex = lookupHexId(key);
|
|
44577
44625
|
if (hex !== void 0) return {
|
|
44578
44626
|
kind: "measurement",
|
|
44579
|
-
quantity: hex.quantity
|
|
44627
|
+
quantity: hex.quantity,
|
|
44628
|
+
name: hex.name
|
|
44580
44629
|
};
|
|
44581
44630
|
const named = Object.prototype.hasOwnProperty.call(NAMED_QUANTITY, key) ? NAMED_QUANTITY[key] : void 0;
|
|
44582
44631
|
if (named !== void 0) return {
|
|
@@ -44612,6 +44661,7 @@ var Station = class {
|
|
|
44612
44661
|
...owner !== void 0 ? { hardwareId: owner } : {},
|
|
44613
44662
|
...info?.model ? { model: info.model } : {},
|
|
44614
44663
|
...info?.channel !== void 0 ? { channel: info.channel } : {},
|
|
44664
|
+
...cls.name !== void 0 ? { name: cls.name } : {},
|
|
44615
44665
|
quantity: cls.quantity,
|
|
44616
44666
|
value: r.value,
|
|
44617
44667
|
unit: r.unit,
|
|
@@ -44645,6 +44695,7 @@ var Station = class {
|
|
|
44645
44695
|
this.upsert(id, {
|
|
44646
44696
|
id,
|
|
44647
44697
|
...r.channel !== void 0 ? { channel: r.channel } : {},
|
|
44698
|
+
...cls.name !== void 0 ? { name: cls.name } : {},
|
|
44648
44699
|
quantity: cls.quantity,
|
|
44649
44700
|
value: r.value,
|
|
44650
44701
|
unit: r.unit,
|
|
@@ -45670,15 +45721,18 @@ function valueFieldForCap(cap) {
|
|
|
45670
45721
|
}
|
|
45671
45722
|
}
|
|
45672
45723
|
/**
|
|
45673
|
-
* Build a human label for a sensor
|
|
45674
|
-
*
|
|
45724
|
+
* Build a human label for a sensor. Prefers the SPECIFIC measurement `name` when
|
|
45725
|
+
* the library resolved one (e.g. "Outdoor Temperature", "Dewpoint Temperature",
|
|
45726
|
+
* "Wind Gust") so same-quantity sensors are distinguishable; otherwise falls back
|
|
45727
|
+
* to the quantity label. A channel suffix is appended when present
|
|
45728
|
+
* (`temperature` + channel 2 → `Temperature CH2`).
|
|
45675
45729
|
*
|
|
45676
45730
|
* Accepts a plain `string` (not just {@link Quantity}) so a persisted config
|
|
45677
45731
|
* value flows through without a cast; an unknown quantity falls back to its raw
|
|
45678
45732
|
* string label.
|
|
45679
45733
|
*/
|
|
45680
|
-
function sensorLabel(quantity, channel) {
|
|
45681
|
-
const base = isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
|
|
45734
|
+
function sensorLabel(quantity, channel, name) {
|
|
45735
|
+
const base = name !== void 0 && name.length > 0 ? name : isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
|
|
45682
45736
|
return channel !== void 0 ? `${base} CH${channel}` : base;
|
|
45683
45737
|
}
|
|
45684
45738
|
/** Type guard: is `q` one of the known {@link Quantity} union members? */
|
|
@@ -45712,7 +45766,7 @@ var QUANTITY_LABEL = {
|
|
|
45712
45766
|
function buildEcowittGatewayCandidate(input) {
|
|
45713
45767
|
const children = input.sensors.map((sensor) => ({
|
|
45714
45768
|
childNativeId: sensor.id,
|
|
45715
|
-
name: sensorLabel(sensor.quantity, sensor.channel),
|
|
45769
|
+
name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
|
|
45716
45770
|
type: DeviceType.Sensor,
|
|
45717
45771
|
status: "online",
|
|
45718
45772
|
metadata: sensor.model !== void 0 ? { model: sensor.model } : {},
|
|
@@ -46187,7 +46241,8 @@ function clampForCap(cap, value) {
|
|
|
46187
46241
|
var ecowittSensorEntrySchema = object({
|
|
46188
46242
|
sensorId: string(),
|
|
46189
46243
|
quantity: string(),
|
|
46190
|
-
channel: number().optional()
|
|
46244
|
+
channel: number().optional(),
|
|
46245
|
+
name: string().optional()
|
|
46191
46246
|
});
|
|
46192
46247
|
/**
|
|
46193
46248
|
* Persisted config for an Ecowitt gateway Container. `brokerId` selects the
|
|
@@ -46230,7 +46285,7 @@ var EcowittContainerDevice = class extends BaseDevice {
|
|
|
46230
46285
|
const meta = {
|
|
46231
46286
|
type: DeviceType.Sensor,
|
|
46232
46287
|
role: roleForQuantity(sensor.quantity),
|
|
46233
|
-
name: sensorLabel(sensor.quantity, sensor.channel),
|
|
46288
|
+
name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
|
|
46234
46289
|
linkDeviceId: this.id,
|
|
46235
46290
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
46236
46291
|
};
|
|
@@ -46385,7 +46440,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
|
|
|
46385
46440
|
const nextSensors = sensors.map((s) => ({
|
|
46386
46441
|
sensorId: s.id,
|
|
46387
46442
|
quantity: s.quantity,
|
|
46388
|
-
...s.channel !== void 0 ? { channel: s.channel } : {}
|
|
46443
|
+
...s.channel !== void 0 ? { channel: s.channel } : {},
|
|
46444
|
+
...s.name !== void 0 ? { name: s.name } : {}
|
|
46389
46445
|
}));
|
|
46390
46446
|
const cfg = await devices.loadConfig(containerId).catch(() => ({}));
|
|
46391
46447
|
if (sensorsEqual(Array.isArray(cfg["sensors"]) ? cfg["sensors"] : [], nextSensors)) return;
|
|
@@ -46506,7 +46562,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
|
|
|
46506
46562
|
sensors: ecowittFacades.getSensors(brokerId).map((s) => ({
|
|
46507
46563
|
sensorId: s.id,
|
|
46508
46564
|
quantity: s.quantity,
|
|
46509
|
-
...s.channel !== void 0 ? { channel: s.channel } : {}
|
|
46565
|
+
...s.channel !== void 0 ? { channel: s.channel } : {},
|
|
46566
|
+
...s.name !== void 0 ? { name: s.name } : {}
|
|
46510
46567
|
})),
|
|
46511
46568
|
system: "ecowitt",
|
|
46512
46569
|
integrationId,
|
|
@@ -46574,12 +46631,18 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
|
|
|
46574
46631
|
/** Structural equality of two persisted sensor lists (order-independent by id). */
|
|
46575
46632
|
function sensorsEqual(a, b) {
|
|
46576
46633
|
if (a.length !== b.length) return false;
|
|
46577
|
-
const
|
|
46634
|
+
const aById = /* @__PURE__ */ new Map();
|
|
46578
46635
|
for (const entry of a) if (typeof entry === "object" && entry !== null && "sensorId" in entry) {
|
|
46579
46636
|
const id = entry.sensorId;
|
|
46580
|
-
if (typeof id === "string")
|
|
46637
|
+
if (typeof id === "string") {
|
|
46638
|
+
const name = "name" in entry && typeof entry.name === "string" ? entry.name : void 0;
|
|
46639
|
+
aById.set(id, name);
|
|
46640
|
+
}
|
|
46641
|
+
}
|
|
46642
|
+
for (const entry of b) {
|
|
46643
|
+
if (!aById.has(entry.sensorId)) return false;
|
|
46644
|
+
if (aById.get(entry.sensorId) !== entry.name) return false;
|
|
46581
46645
|
}
|
|
46582
|
-
for (const entry of b) if (!aIds.has(entry.sensorId)) return false;
|
|
46583
46646
|
return true;
|
|
46584
46647
|
}
|
|
46585
46648
|
//#endregion
|
package/dist/addon.mjs
CHANGED
|
@@ -10083,15 +10083,18 @@ var humiditySensorCapability = {
|
|
|
10083
10083
|
runtimeState: HumiditySensorStatusSchema
|
|
10084
10084
|
};
|
|
10085
10085
|
/**
|
|
10086
|
-
* Image display cap. Models
|
|
10087
|
-
*
|
|
10086
|
+
* Image display cap. Models a single still image exposed by an integration —
|
|
10087
|
+
* a snapshot, a chart, a generated picture, or a robot's cleaning-map render.
|
|
10088
10088
|
*
|
|
10089
|
-
* Read-only: there are no setters. The provider resolves
|
|
10090
|
-
*
|
|
10091
|
-
*
|
|
10092
|
-
*
|
|
10093
|
-
*
|
|
10094
|
-
*
|
|
10089
|
+
* Read-only: there are no setters. The provider resolves whatever upstream
|
|
10090
|
+
* source it has into an ABSOLUTE URL the browser loads directly:
|
|
10091
|
+
* - HA `image.*` entities → the `entity_picture` signed-token path
|
|
10092
|
+
* (token stays in the query string, so no auth header is needed);
|
|
10093
|
+
* - a Dreame/robot map → the cloud/OSS map-image URL (or an addon
|
|
10094
|
+
* data-plane URL serving the rendered map bytes), exposed as its own
|
|
10095
|
+
* Image child device grouped under the robot's container.
|
|
10096
|
+
* The slice carries that URL plus the upstream last-updated timestamp; the
|
|
10097
|
+
* image changes when the source's last-updated marker changes.
|
|
10095
10098
|
*/
|
|
10096
10099
|
var ImageStatusSchema = object({
|
|
10097
10100
|
/** Absolute signed URL the browser loads directly. Null when the
|
|
@@ -10117,18 +10120,47 @@ var imageCapability = {
|
|
|
10117
10120
|
*/
|
|
10118
10121
|
runtimeState: ImageStatusSchema
|
|
10119
10122
|
};
|
|
10123
|
+
/**
|
|
10124
|
+
* Robotic lawn-mower cap. Models HA `lawn_mower.*` entities — anything
|
|
10125
|
+
* with a mowing lifecycle plus a dock action.
|
|
10126
|
+
*
|
|
10127
|
+
* Activity follows HA's canonical lawn-mower lifecycle: `idle` /
|
|
10128
|
+
* `mowing` / `paused` / `docked` / `error`. `batteryLevel` (0..100) is
|
|
10129
|
+
* nullable — some mowers don't report a battery percentage.
|
|
10130
|
+
*
|
|
10131
|
+
* `startMowing` begins a mowing run, `pause` halts it in place, and
|
|
10132
|
+
* `dock` sends the mower back to its charging station.
|
|
10133
|
+
*/
|
|
10134
|
+
var LawnMowerActivitySchema = _enum([
|
|
10135
|
+
"idle",
|
|
10136
|
+
"mowing",
|
|
10137
|
+
"paused",
|
|
10138
|
+
"docked",
|
|
10139
|
+
"error"
|
|
10140
|
+
]);
|
|
10141
|
+
/** Severity of the current device/error code — info (status), warning, error. */
|
|
10142
|
+
var DeviceCodeSeveritySchema = _enum([
|
|
10143
|
+
"info",
|
|
10144
|
+
"warning",
|
|
10145
|
+
"error"
|
|
10146
|
+
]);
|
|
10120
10147
|
var LawnMowerControlStatusSchema = object({
|
|
10121
10148
|
/** Lifecycle activity of the mower. */
|
|
10122
|
-
activity:
|
|
10123
|
-
"idle",
|
|
10124
|
-
"mowing",
|
|
10125
|
-
"paused",
|
|
10126
|
-
"docked",
|
|
10127
|
-
"error"
|
|
10128
|
-
]),
|
|
10149
|
+
activity: LawnMowerActivitySchema,
|
|
10129
10150
|
/** 0..100 battery percentage. Null when the device has no battery
|
|
10130
10151
|
* reading. */
|
|
10131
10152
|
batteryLevel: number().min(0).max(100).nullable(),
|
|
10153
|
+
/** 0..100 mowing-completion percentage of the current task, or null when no
|
|
10154
|
+
* task is active / progress is unavailable. */
|
|
10155
|
+
progressPercent: number().min(0).max(100).nullable(),
|
|
10156
|
+
/** Current device/event code (dynamic — mostly status, sometimes an error),
|
|
10157
|
+
* or null when unknown. */
|
|
10158
|
+
currentCode: number().nullable(),
|
|
10159
|
+
/** Human label for {@link currentCode}, or null when undecodable. */
|
|
10160
|
+
currentCodeLabel: string().nullable(),
|
|
10161
|
+
/** Severity of {@link currentCode}. `error` (and often `warning`) warrants UI
|
|
10162
|
+
* attention; `info` is normal status. */
|
|
10163
|
+
severity: DeviceCodeSeveritySchema,
|
|
10132
10164
|
/** Ms epoch when the slice was last updated. */
|
|
10133
10165
|
lastChangedAt: number()
|
|
10134
10166
|
});
|
|
@@ -12354,6 +12386,7 @@ var VacuumStateSchema = _enum([
|
|
|
12354
12386
|
"paused",
|
|
12355
12387
|
"returning",
|
|
12356
12388
|
"docked",
|
|
12389
|
+
"drying",
|
|
12357
12390
|
"error"
|
|
12358
12391
|
]);
|
|
12359
12392
|
/**
|
|
@@ -12392,6 +12425,12 @@ var VacuumControlStatusSchema = object({
|
|
|
12392
12425
|
detergent: TankStatusSchema.nullable(),
|
|
12393
12426
|
/** Dust bin. Null when the hardware has no dust bin. */
|
|
12394
12427
|
dustBin: TankStatusSchema.nullable(),
|
|
12428
|
+
/** 0..100 cleaning-completion percentage of the current task, or null. */
|
|
12429
|
+
progressPercent: number().min(0).max(100).nullable(),
|
|
12430
|
+
/** Current error code (0 / null = no error). */
|
|
12431
|
+
errorCode: number().nullable(),
|
|
12432
|
+
/** Human label for {@link errorCode}, or null when none / undecodable. */
|
|
12433
|
+
errorLabel: string().nullable(),
|
|
12395
12434
|
/** Ms epoch when the slice was last updated. */
|
|
12396
12435
|
lastChangedAt: number()
|
|
12397
12436
|
});
|
|
@@ -16907,6 +16946,9 @@ method(object({
|
|
|
16907
16946
|
}), method(ReleaseInputSchema.extend({ addonId: string() }), _void(), {
|
|
16908
16947
|
kind: "mutation",
|
|
16909
16948
|
auth: "admin"
|
|
16949
|
+
}), method(ResyncInputSchema, ResyncResultSchema, {
|
|
16950
|
+
kind: "mutation",
|
|
16951
|
+
auth: "admin"
|
|
16910
16952
|
}), method(object({
|
|
16911
16953
|
deviceId: number(),
|
|
16912
16954
|
key: string(),
|
|
@@ -20669,6 +20711,12 @@ Object.freeze({
|
|
|
20669
20711
|
addonId: null,
|
|
20670
20712
|
access: "create"
|
|
20671
20713
|
},
|
|
20714
|
+
"deviceManager.adoptionResync": {
|
|
20715
|
+
capName: "device-manager",
|
|
20716
|
+
capScope: "system",
|
|
20717
|
+
addonId: null,
|
|
20718
|
+
access: "create"
|
|
20719
|
+
},
|
|
20672
20720
|
"deviceManager.allocateDeviceId": {
|
|
20673
20721
|
capName: "device-manager",
|
|
20674
20722
|
capScope: "system",
|
|
@@ -44577,7 +44625,8 @@ function classifyKey(key) {
|
|
|
44577
44625
|
const hex = lookupHexId(key);
|
|
44578
44626
|
if (hex !== void 0) return {
|
|
44579
44627
|
kind: "measurement",
|
|
44580
|
-
quantity: hex.quantity
|
|
44628
|
+
quantity: hex.quantity,
|
|
44629
|
+
name: hex.name
|
|
44581
44630
|
};
|
|
44582
44631
|
const named = Object.prototype.hasOwnProperty.call(NAMED_QUANTITY, key) ? NAMED_QUANTITY[key] : void 0;
|
|
44583
44632
|
if (named !== void 0) return {
|
|
@@ -44613,6 +44662,7 @@ var Station = class {
|
|
|
44613
44662
|
...owner !== void 0 ? { hardwareId: owner } : {},
|
|
44614
44663
|
...info?.model ? { model: info.model } : {},
|
|
44615
44664
|
...info?.channel !== void 0 ? { channel: info.channel } : {},
|
|
44665
|
+
...cls.name !== void 0 ? { name: cls.name } : {},
|
|
44616
44666
|
quantity: cls.quantity,
|
|
44617
44667
|
value: r.value,
|
|
44618
44668
|
unit: r.unit,
|
|
@@ -44646,6 +44696,7 @@ var Station = class {
|
|
|
44646
44696
|
this.upsert(id, {
|
|
44647
44697
|
id,
|
|
44648
44698
|
...r.channel !== void 0 ? { channel: r.channel } : {},
|
|
44699
|
+
...cls.name !== void 0 ? { name: cls.name } : {},
|
|
44649
44700
|
quantity: cls.quantity,
|
|
44650
44701
|
value: r.value,
|
|
44651
44702
|
unit: r.unit,
|
|
@@ -45671,15 +45722,18 @@ function valueFieldForCap(cap) {
|
|
|
45671
45722
|
}
|
|
45672
45723
|
}
|
|
45673
45724
|
/**
|
|
45674
|
-
* Build a human label for a sensor
|
|
45675
|
-
*
|
|
45725
|
+
* Build a human label for a sensor. Prefers the SPECIFIC measurement `name` when
|
|
45726
|
+
* the library resolved one (e.g. "Outdoor Temperature", "Dewpoint Temperature",
|
|
45727
|
+
* "Wind Gust") so same-quantity sensors are distinguishable; otherwise falls back
|
|
45728
|
+
* to the quantity label. A channel suffix is appended when present
|
|
45729
|
+
* (`temperature` + channel 2 → `Temperature CH2`).
|
|
45676
45730
|
*
|
|
45677
45731
|
* Accepts a plain `string` (not just {@link Quantity}) so a persisted config
|
|
45678
45732
|
* value flows through without a cast; an unknown quantity falls back to its raw
|
|
45679
45733
|
* string label.
|
|
45680
45734
|
*/
|
|
45681
|
-
function sensorLabel(quantity, channel) {
|
|
45682
|
-
const base = isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
|
|
45735
|
+
function sensorLabel(quantity, channel, name) {
|
|
45736
|
+
const base = name !== void 0 && name.length > 0 ? name : isKnownQuantity(quantity) ? QUANTITY_LABEL[quantity] : quantity;
|
|
45683
45737
|
return channel !== void 0 ? `${base} CH${channel}` : base;
|
|
45684
45738
|
}
|
|
45685
45739
|
/** Type guard: is `q` one of the known {@link Quantity} union members? */
|
|
@@ -45713,7 +45767,7 @@ var QUANTITY_LABEL = {
|
|
|
45713
45767
|
function buildEcowittGatewayCandidate(input) {
|
|
45714
45768
|
const children = input.sensors.map((sensor) => ({
|
|
45715
45769
|
childNativeId: sensor.id,
|
|
45716
|
-
name: sensorLabel(sensor.quantity, sensor.channel),
|
|
45770
|
+
name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
|
|
45717
45771
|
type: DeviceType.Sensor,
|
|
45718
45772
|
status: "online",
|
|
45719
45773
|
metadata: sensor.model !== void 0 ? { model: sensor.model } : {},
|
|
@@ -46188,7 +46242,8 @@ function clampForCap(cap, value) {
|
|
|
46188
46242
|
var ecowittSensorEntrySchema = object({
|
|
46189
46243
|
sensorId: string(),
|
|
46190
46244
|
quantity: string(),
|
|
46191
|
-
channel: number().optional()
|
|
46245
|
+
channel: number().optional(),
|
|
46246
|
+
name: string().optional()
|
|
46192
46247
|
});
|
|
46193
46248
|
/**
|
|
46194
46249
|
* Persisted config for an Ecowitt gateway Container. `brokerId` selects the
|
|
@@ -46231,7 +46286,7 @@ var EcowittContainerDevice = class extends BaseDevice {
|
|
|
46231
46286
|
const meta = {
|
|
46232
46287
|
type: DeviceType.Sensor,
|
|
46233
46288
|
role: roleForQuantity(sensor.quantity),
|
|
46234
|
-
name: sensorLabel(sensor.quantity, sensor.channel),
|
|
46289
|
+
name: sensorLabel(sensor.quantity, sensor.channel, sensor.name),
|
|
46235
46290
|
linkDeviceId: this.id,
|
|
46236
46291
|
...this.integrationId !== void 0 ? { integrationId: this.integrationId } : {}
|
|
46237
46292
|
};
|
|
@@ -46386,7 +46441,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
|
|
|
46386
46441
|
const nextSensors = sensors.map((s) => ({
|
|
46387
46442
|
sensorId: s.id,
|
|
46388
46443
|
quantity: s.quantity,
|
|
46389
|
-
...s.channel !== void 0 ? { channel: s.channel } : {}
|
|
46444
|
+
...s.channel !== void 0 ? { channel: s.channel } : {},
|
|
46445
|
+
...s.name !== void 0 ? { name: s.name } : {}
|
|
46390
46446
|
}));
|
|
46391
46447
|
const cfg = await devices.loadConfig(containerId).catch(() => ({}));
|
|
46392
46448
|
if (sensorsEqual(Array.isArray(cfg["sensors"]) ? cfg["sensors"] : [], nextSensors)) return;
|
|
@@ -46507,7 +46563,8 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
|
|
|
46507
46563
|
sensors: ecowittFacades.getSensors(brokerId).map((s) => ({
|
|
46508
46564
|
sensorId: s.id,
|
|
46509
46565
|
quantity: s.quantity,
|
|
46510
|
-
...s.channel !== void 0 ? { channel: s.channel } : {}
|
|
46566
|
+
...s.channel !== void 0 ? { channel: s.channel } : {},
|
|
46567
|
+
...s.name !== void 0 ? { name: s.name } : {}
|
|
46511
46568
|
})),
|
|
46512
46569
|
system: "ecowitt",
|
|
46513
46570
|
integrationId,
|
|
@@ -46575,12 +46632,18 @@ var EcowittProviderAddon = class extends BaseDeviceProvider {
|
|
|
46575
46632
|
/** Structural equality of two persisted sensor lists (order-independent by id). */
|
|
46576
46633
|
function sensorsEqual(a, b) {
|
|
46577
46634
|
if (a.length !== b.length) return false;
|
|
46578
|
-
const
|
|
46635
|
+
const aById = /* @__PURE__ */ new Map();
|
|
46579
46636
|
for (const entry of a) if (typeof entry === "object" && entry !== null && "sensorId" in entry) {
|
|
46580
46637
|
const id = entry.sensorId;
|
|
46581
|
-
if (typeof id === "string")
|
|
46638
|
+
if (typeof id === "string") {
|
|
46639
|
+
const name = "name" in entry && typeof entry.name === "string" ? entry.name : void 0;
|
|
46640
|
+
aById.set(id, name);
|
|
46641
|
+
}
|
|
46642
|
+
}
|
|
46643
|
+
for (const entry of b) {
|
|
46644
|
+
if (!aById.has(entry.sensorId)) return false;
|
|
46645
|
+
if (aById.get(entry.sensorId) !== entry.name) return false;
|
|
46582
46646
|
}
|
|
46583
|
-
for (const entry of b) if (!aIds.has(entry.sensorId)) return false;
|
|
46584
46647
|
return true;
|
|
46585
46648
|
}
|
|
46586
46649
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-provider-ecowitt",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Ecowitt weather-station device-provider addon for CamStack — wraps the @apocaliss92/nodewitt local-poll / push client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"publish": "npm publish --access public"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@apocaliss92/nodewitt": "^1.
|
|
74
|
+
"@apocaliss92/nodewitt": "^1.2.0",
|
|
75
75
|
"@camstack/types": "*",
|
|
76
76
|
"typescript": "~6.0.3",
|
|
77
77
|
"vite": "^8.0.11",
|