@camstack/addon-provider-homeassistant 1.2.81 → 1.2.82
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 +92 -28
- package/dist/addon.mjs +92 -28
- package/dist/{dist-HZncHwuU.js → dist-GeeaZrMS.js} +22 -4
- package/dist/{dist-BpePMREY.mjs → dist-ru9DzHlP.mjs} +22 -4
- package/dist/ha-export/ha-export.addon.js +5 -4
- package/dist/ha-export/ha-export.addon.mjs +5 -4
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-GeeaZrMS.js");
|
|
3
3
|
let node_crypto = require("node:crypto");
|
|
4
4
|
let node_zlib = require("node:zlib");
|
|
5
5
|
//#region src/ha-device-source.ts
|
|
@@ -1410,31 +1410,14 @@ var HaClimateDevice = class extends HaBaseChildDevice {
|
|
|
1410
1410
|
this.registerClimateCap();
|
|
1411
1411
|
this.runtimeState.setCapState("climate-control", COLD_START$15);
|
|
1412
1412
|
}
|
|
1413
|
+
/** The louver vocabularies HA last advertised, for the swing setters. */
|
|
1414
|
+
swingModes = [];
|
|
1415
|
+
swingHorizontalModes = [];
|
|
1413
1416
|
handleStatePush(state) {
|
|
1414
1417
|
if (state.state === "unavailable" || state.state === "unknown") return;
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
const availableModes = readStringArray$4(attrs, "hvac_modes").map(sanitizeHvacMode).filter((m) => m !== null);
|
|
1419
|
-
const fanMode = readStringAttr$6(attrs, "fan_mode") ?? "";
|
|
1420
|
-
const availableFanModes = readStringArray$4(attrs, "fan_modes");
|
|
1421
|
-
const preset = readStringAttr$6(attrs, "preset_mode") ?? "";
|
|
1422
|
-
const availablePresets = readStringArray$4(attrs, "preset_modes");
|
|
1423
|
-
this.runtimeState.setCapState("climate-control", {
|
|
1424
|
-
mode: mode ?? "off",
|
|
1425
|
-
availableModes,
|
|
1426
|
-
fanMode,
|
|
1427
|
-
availableFanModes,
|
|
1428
|
-
preset,
|
|
1429
|
-
availablePresets,
|
|
1430
|
-
target: readNumberAttr$5(attrs, "temperature"),
|
|
1431
|
-
targetHigh: readNumberAttr$5(attrs, "target_temp_high"),
|
|
1432
|
-
targetLow: readNumberAttr$5(attrs, "target_temp_low"),
|
|
1433
|
-
targetHumidity: readNumberAttr$5(attrs, "target_humidity"),
|
|
1434
|
-
currentTemp: readNumberAttr$5(attrs, "current_temperature"),
|
|
1435
|
-
currentHumidity: readNumberAttr$5(attrs, "current_humidity"),
|
|
1436
|
-
lastFetchedAt
|
|
1437
|
-
});
|
|
1418
|
+
this.swingModes = readStringArray$4(state.attributes, "swing_modes");
|
|
1419
|
+
this.swingHorizontalModes = readStringArray$4(state.attributes, "swing_horizontal_modes");
|
|
1420
|
+
this.runtimeState.setCapState("climate-control", climateSliceFromState(state));
|
|
1438
1421
|
}
|
|
1439
1422
|
registerClimateCap() {
|
|
1440
1423
|
this.ctx.registerNativeCap(require_dist.climateControlCapability, {
|
|
@@ -1462,15 +1445,96 @@ var HaClimateDevice = class extends HaBaseChildDevice {
|
|
|
1462
1445
|
setTargetHumidity: async ({ targetHumidity }) => {
|
|
1463
1446
|
await this.callHaService("climate", "set_humidity", { humidity: targetHumidity });
|
|
1464
1447
|
},
|
|
1465
|
-
setSwingVertical: async () => {
|
|
1466
|
-
|
|
1448
|
+
setSwingVertical: async ({ on }) => {
|
|
1449
|
+
const swingMode = pickSwingMode(this.swingModes, on, VERTICAL_ON_MODES);
|
|
1450
|
+
if (swingMode === null) throw new Error("HaClimateDevice: vertical swing not supported");
|
|
1451
|
+
await this.callHaService("climate", "set_swing_mode", { swing_mode: swingMode });
|
|
1467
1452
|
},
|
|
1468
|
-
setSwingHorizontal: async () => {
|
|
1469
|
-
|
|
1453
|
+
setSwingHorizontal: async ({ on }) => {
|
|
1454
|
+
if (this.swingHorizontalModes.length > 0) {
|
|
1455
|
+
const mode = pickSwingMode(this.swingHorizontalModes, on, HORIZONTAL_ON_MODES);
|
|
1456
|
+
if (mode === null) throw new Error("HaClimateDevice: horizontal swing not supported");
|
|
1457
|
+
await this.callHaService("climate", "set_swing_horizontal_mode", { swing_horizontal_mode: mode });
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
const swingMode = pickSwingMode(this.swingModes, on, HORIZONTAL_ON_MODES);
|
|
1461
|
+
if (swingMode === null) throw new Error("HaClimateDevice: horizontal swing not supported");
|
|
1462
|
+
await this.callHaService("climate", "set_swing_mode", { swing_mode: swingMode });
|
|
1470
1463
|
}
|
|
1471
1464
|
});
|
|
1472
1465
|
}
|
|
1473
1466
|
};
|
|
1467
|
+
/**
|
|
1468
|
+
* The `climate-control` slice for one HA `climate.*` state. Pure, and the ONLY
|
|
1469
|
+
* place the slice is assembled: every key the cap schema declares is present —
|
|
1470
|
+
* `swingVertical` / `swingHorizontal` are `nullable`, not optional, and a slice
|
|
1471
|
+
* that omitted them was refused by `setCapState` on every push (828 dropped
|
|
1472
|
+
* pushes in a day on the live hub, every thermostat stuck at its cold start).
|
|
1473
|
+
*/
|
|
1474
|
+
function climateSliceFromState(state) {
|
|
1475
|
+
const lastFetchedAt = Date.parse(state.last_updated) || Date.now();
|
|
1476
|
+
const attrs = state.attributes;
|
|
1477
|
+
const mode = sanitizeHvacMode(state.state);
|
|
1478
|
+
const availableModes = readStringArray$4(attrs, "hvac_modes").map(sanitizeHvacMode).filter((m) => m !== null);
|
|
1479
|
+
const fanMode = readStringAttr$6(attrs, "fan_mode") ?? "";
|
|
1480
|
+
const availableFanModes = readStringArray$4(attrs, "fan_modes");
|
|
1481
|
+
const preset = readStringAttr$6(attrs, "preset_mode") ?? "";
|
|
1482
|
+
const availablePresets = readStringArray$4(attrs, "preset_modes");
|
|
1483
|
+
return {
|
|
1484
|
+
mode: mode ?? "off",
|
|
1485
|
+
availableModes,
|
|
1486
|
+
fanMode,
|
|
1487
|
+
availableFanModes,
|
|
1488
|
+
preset,
|
|
1489
|
+
availablePresets,
|
|
1490
|
+
target: readNumberAttr$5(attrs, "temperature"),
|
|
1491
|
+
targetHigh: readNumberAttr$5(attrs, "target_temp_high"),
|
|
1492
|
+
targetLow: readNumberAttr$5(attrs, "target_temp_low"),
|
|
1493
|
+
targetHumidity: readNumberAttr$5(attrs, "target_humidity"),
|
|
1494
|
+
currentTemp: readNumberAttr$5(attrs, "current_temperature"),
|
|
1495
|
+
currentHumidity: readNumberAttr$5(attrs, "current_humidity"),
|
|
1496
|
+
...readSwing(attrs),
|
|
1497
|
+
lastFetchedAt
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
/** HA `swing_mode` values that mean the VERTICAL louver is moving. */
|
|
1501
|
+
var VERTICAL_ON_MODES = [
|
|
1502
|
+
"vertical",
|
|
1503
|
+
"both",
|
|
1504
|
+
"on"
|
|
1505
|
+
];
|
|
1506
|
+
/** HA `swing_mode` / `swing_horizontal_mode` values that mean the HORIZONTAL louver is moving. */
|
|
1507
|
+
var HORIZONTAL_ON_MODES = [
|
|
1508
|
+
"horizontal",
|
|
1509
|
+
"both",
|
|
1510
|
+
"on"
|
|
1511
|
+
];
|
|
1512
|
+
/**
|
|
1513
|
+
* HA models swing as one `swing_mode` picked from `swing_modes` (`off`,
|
|
1514
|
+
* `vertical`, `horizontal`, `both`, vendor strings), plus — on newer cores —
|
|
1515
|
+
* a separate `swing_horizontal_mode`. An axis the device never advertised is
|
|
1516
|
+
* `null`: no vocabulary, no control (D62).
|
|
1517
|
+
*/
|
|
1518
|
+
function readSwing(attrs) {
|
|
1519
|
+
const swingModes = readStringArray$4(attrs, "swing_modes");
|
|
1520
|
+
const horizontalModes = readStringArray$4(attrs, "swing_horizontal_modes");
|
|
1521
|
+
const swingMode = (readStringAttr$6(attrs, "swing_mode") ?? "").toLowerCase();
|
|
1522
|
+
const horizontalMode = (readStringAttr$6(attrs, "swing_horizontal_mode") ?? "").toLowerCase();
|
|
1523
|
+
return {
|
|
1524
|
+
swingVertical: swingModes.length === 0 ? null : VERTICAL_ON_MODES.includes(swingMode),
|
|
1525
|
+
swingHorizontal: horizontalModes.length > 0 ? HORIZONTAL_ON_MODES.includes(horizontalMode) : swingModes.some((m) => HORIZONTAL_ON_MODES.includes(m.toLowerCase())) ? HORIZONTAL_ON_MODES.includes(swingMode) : null
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* The HA mode that turns one axis on or off, chosen from what the device
|
|
1530
|
+
* advertised; `null` when the vocabulary has no such value.
|
|
1531
|
+
*/
|
|
1532
|
+
function pickSwingMode(advertised, enabled, onModes) {
|
|
1533
|
+
const lower = advertised.map((m) => m.toLowerCase());
|
|
1534
|
+
const wanted = enabled ? onModes : ["off"];
|
|
1535
|
+
const index = lower.findIndex((m) => wanted.includes(m));
|
|
1536
|
+
return index === -1 ? null : advertised[index] ?? null;
|
|
1537
|
+
}
|
|
1474
1538
|
function sanitizeHvacMode(s) {
|
|
1475
1539
|
switch (s) {
|
|
1476
1540
|
case "off":
|
package/dist/addon.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-
|
|
1
|
+
import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-ru9DzHlP.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
|
|
4
4
|
//#region src/ha-device-source.ts
|
|
@@ -1409,31 +1409,14 @@ var HaClimateDevice = class extends HaBaseChildDevice {
|
|
|
1409
1409
|
this.registerClimateCap();
|
|
1410
1410
|
this.runtimeState.setCapState("climate-control", COLD_START$15);
|
|
1411
1411
|
}
|
|
1412
|
+
/** The louver vocabularies HA last advertised, for the swing setters. */
|
|
1413
|
+
swingModes = [];
|
|
1414
|
+
swingHorizontalModes = [];
|
|
1412
1415
|
handleStatePush(state) {
|
|
1413
1416
|
if (state.state === "unavailable" || state.state === "unknown") return;
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
const availableModes = readStringArray$4(attrs, "hvac_modes").map(sanitizeHvacMode).filter((m) => m !== null);
|
|
1418
|
-
const fanMode = readStringAttr$6(attrs, "fan_mode") ?? "";
|
|
1419
|
-
const availableFanModes = readStringArray$4(attrs, "fan_modes");
|
|
1420
|
-
const preset = readStringAttr$6(attrs, "preset_mode") ?? "";
|
|
1421
|
-
const availablePresets = readStringArray$4(attrs, "preset_modes");
|
|
1422
|
-
this.runtimeState.setCapState("climate-control", {
|
|
1423
|
-
mode: mode ?? "off",
|
|
1424
|
-
availableModes,
|
|
1425
|
-
fanMode,
|
|
1426
|
-
availableFanModes,
|
|
1427
|
-
preset,
|
|
1428
|
-
availablePresets,
|
|
1429
|
-
target: readNumberAttr$5(attrs, "temperature"),
|
|
1430
|
-
targetHigh: readNumberAttr$5(attrs, "target_temp_high"),
|
|
1431
|
-
targetLow: readNumberAttr$5(attrs, "target_temp_low"),
|
|
1432
|
-
targetHumidity: readNumberAttr$5(attrs, "target_humidity"),
|
|
1433
|
-
currentTemp: readNumberAttr$5(attrs, "current_temperature"),
|
|
1434
|
-
currentHumidity: readNumberAttr$5(attrs, "current_humidity"),
|
|
1435
|
-
lastFetchedAt
|
|
1436
|
-
});
|
|
1417
|
+
this.swingModes = readStringArray$4(state.attributes, "swing_modes");
|
|
1418
|
+
this.swingHorizontalModes = readStringArray$4(state.attributes, "swing_horizontal_modes");
|
|
1419
|
+
this.runtimeState.setCapState("climate-control", climateSliceFromState(state));
|
|
1437
1420
|
}
|
|
1438
1421
|
registerClimateCap() {
|
|
1439
1422
|
this.ctx.registerNativeCap(climateControlCapability, {
|
|
@@ -1461,15 +1444,96 @@ var HaClimateDevice = class extends HaBaseChildDevice {
|
|
|
1461
1444
|
setTargetHumidity: async ({ targetHumidity }) => {
|
|
1462
1445
|
await this.callHaService("climate", "set_humidity", { humidity: targetHumidity });
|
|
1463
1446
|
},
|
|
1464
|
-
setSwingVertical: async () => {
|
|
1465
|
-
|
|
1447
|
+
setSwingVertical: async ({ on }) => {
|
|
1448
|
+
const swingMode = pickSwingMode(this.swingModes, on, VERTICAL_ON_MODES);
|
|
1449
|
+
if (swingMode === null) throw new Error("HaClimateDevice: vertical swing not supported");
|
|
1450
|
+
await this.callHaService("climate", "set_swing_mode", { swing_mode: swingMode });
|
|
1466
1451
|
},
|
|
1467
|
-
setSwingHorizontal: async () => {
|
|
1468
|
-
|
|
1452
|
+
setSwingHorizontal: async ({ on }) => {
|
|
1453
|
+
if (this.swingHorizontalModes.length > 0) {
|
|
1454
|
+
const mode = pickSwingMode(this.swingHorizontalModes, on, HORIZONTAL_ON_MODES);
|
|
1455
|
+
if (mode === null) throw new Error("HaClimateDevice: horizontal swing not supported");
|
|
1456
|
+
await this.callHaService("climate", "set_swing_horizontal_mode", { swing_horizontal_mode: mode });
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
const swingMode = pickSwingMode(this.swingModes, on, HORIZONTAL_ON_MODES);
|
|
1460
|
+
if (swingMode === null) throw new Error("HaClimateDevice: horizontal swing not supported");
|
|
1461
|
+
await this.callHaService("climate", "set_swing_mode", { swing_mode: swingMode });
|
|
1469
1462
|
}
|
|
1470
1463
|
});
|
|
1471
1464
|
}
|
|
1472
1465
|
};
|
|
1466
|
+
/**
|
|
1467
|
+
* The `climate-control` slice for one HA `climate.*` state. Pure, and the ONLY
|
|
1468
|
+
* place the slice is assembled: every key the cap schema declares is present —
|
|
1469
|
+
* `swingVertical` / `swingHorizontal` are `nullable`, not optional, and a slice
|
|
1470
|
+
* that omitted them was refused by `setCapState` on every push (828 dropped
|
|
1471
|
+
* pushes in a day on the live hub, every thermostat stuck at its cold start).
|
|
1472
|
+
*/
|
|
1473
|
+
function climateSliceFromState(state) {
|
|
1474
|
+
const lastFetchedAt = Date.parse(state.last_updated) || Date.now();
|
|
1475
|
+
const attrs = state.attributes;
|
|
1476
|
+
const mode = sanitizeHvacMode(state.state);
|
|
1477
|
+
const availableModes = readStringArray$4(attrs, "hvac_modes").map(sanitizeHvacMode).filter((m) => m !== null);
|
|
1478
|
+
const fanMode = readStringAttr$6(attrs, "fan_mode") ?? "";
|
|
1479
|
+
const availableFanModes = readStringArray$4(attrs, "fan_modes");
|
|
1480
|
+
const preset = readStringAttr$6(attrs, "preset_mode") ?? "";
|
|
1481
|
+
const availablePresets = readStringArray$4(attrs, "preset_modes");
|
|
1482
|
+
return {
|
|
1483
|
+
mode: mode ?? "off",
|
|
1484
|
+
availableModes,
|
|
1485
|
+
fanMode,
|
|
1486
|
+
availableFanModes,
|
|
1487
|
+
preset,
|
|
1488
|
+
availablePresets,
|
|
1489
|
+
target: readNumberAttr$5(attrs, "temperature"),
|
|
1490
|
+
targetHigh: readNumberAttr$5(attrs, "target_temp_high"),
|
|
1491
|
+
targetLow: readNumberAttr$5(attrs, "target_temp_low"),
|
|
1492
|
+
targetHumidity: readNumberAttr$5(attrs, "target_humidity"),
|
|
1493
|
+
currentTemp: readNumberAttr$5(attrs, "current_temperature"),
|
|
1494
|
+
currentHumidity: readNumberAttr$5(attrs, "current_humidity"),
|
|
1495
|
+
...readSwing(attrs),
|
|
1496
|
+
lastFetchedAt
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
/** HA `swing_mode` values that mean the VERTICAL louver is moving. */
|
|
1500
|
+
var VERTICAL_ON_MODES = [
|
|
1501
|
+
"vertical",
|
|
1502
|
+
"both",
|
|
1503
|
+
"on"
|
|
1504
|
+
];
|
|
1505
|
+
/** HA `swing_mode` / `swing_horizontal_mode` values that mean the HORIZONTAL louver is moving. */
|
|
1506
|
+
var HORIZONTAL_ON_MODES = [
|
|
1507
|
+
"horizontal",
|
|
1508
|
+
"both",
|
|
1509
|
+
"on"
|
|
1510
|
+
];
|
|
1511
|
+
/**
|
|
1512
|
+
* HA models swing as one `swing_mode` picked from `swing_modes` (`off`,
|
|
1513
|
+
* `vertical`, `horizontal`, `both`, vendor strings), plus — on newer cores —
|
|
1514
|
+
* a separate `swing_horizontal_mode`. An axis the device never advertised is
|
|
1515
|
+
* `null`: no vocabulary, no control (D62).
|
|
1516
|
+
*/
|
|
1517
|
+
function readSwing(attrs) {
|
|
1518
|
+
const swingModes = readStringArray$4(attrs, "swing_modes");
|
|
1519
|
+
const horizontalModes = readStringArray$4(attrs, "swing_horizontal_modes");
|
|
1520
|
+
const swingMode = (readStringAttr$6(attrs, "swing_mode") ?? "").toLowerCase();
|
|
1521
|
+
const horizontalMode = (readStringAttr$6(attrs, "swing_horizontal_mode") ?? "").toLowerCase();
|
|
1522
|
+
return {
|
|
1523
|
+
swingVertical: swingModes.length === 0 ? null : VERTICAL_ON_MODES.includes(swingMode),
|
|
1524
|
+
swingHorizontal: horizontalModes.length > 0 ? HORIZONTAL_ON_MODES.includes(horizontalMode) : swingModes.some((m) => HORIZONTAL_ON_MODES.includes(m.toLowerCase())) ? HORIZONTAL_ON_MODES.includes(swingMode) : null
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* The HA mode that turns one axis on or off, chosen from what the device
|
|
1529
|
+
* advertised; `null` when the vocabulary has no such value.
|
|
1530
|
+
*/
|
|
1531
|
+
function pickSwingMode(advertised, enabled, onModes) {
|
|
1532
|
+
const lower = advertised.map((m) => m.toLowerCase());
|
|
1533
|
+
const wanted = enabled ? onModes : ["off"];
|
|
1534
|
+
const index = lower.findIndex((m) => wanted.includes(m));
|
|
1535
|
+
return index === -1 ? null : advertised[index] ?? null;
|
|
1536
|
+
}
|
|
1473
1537
|
function sanitizeHvacMode(s) {
|
|
1474
1538
|
switch (s) {
|
|
1475
1539
|
case "off":
|
|
@@ -7756,7 +7756,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
|
|
|
7756
7756
|
var CameraSwitchUnavailableReasonSchema = _enum([
|
|
7757
7757
|
"no-provider",
|
|
7758
7758
|
"source-unreachable",
|
|
7759
|
-
"not-configured"
|
|
7759
|
+
"not-configured",
|
|
7760
|
+
"device-disabled"
|
|
7760
7761
|
]);
|
|
7761
7762
|
/**
|
|
7762
7763
|
* One switch, resolved for one camera.
|
|
@@ -24036,12 +24037,20 @@ var BatteryStatusSchema = object({
|
|
|
24036
24037
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
24037
24038
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
24038
24039
|
* common on other battery cams). `'none'` means running on battery
|
|
24039
|
-
* alone.
|
|
24040
|
+
* alone — a NEGATIVE the firmware actually reported.
|
|
24041
|
+
*
|
|
24042
|
+
* `'unknown'` is the absence of an answer: the provider has not read the
|
|
24043
|
+
* power fields yet, or the firmware reported neither. Before it existed,
|
|
24044
|
+
* two unreadable fields produced `'none'`, and a camera nobody had reached
|
|
24045
|
+
* was drawn "on battery alone" — the same D315 defect `percentage` closed
|
|
24046
|
+
* by going nullable. Consumers SKIP it (no charger state published, no
|
|
24047
|
+
* glyph, no HomeKit ChargingState) rather than coerce it either way.
|
|
24040
24048
|
*/
|
|
24041
24049
|
charging: _enum([
|
|
24042
24050
|
"dc",
|
|
24043
24051
|
"solar",
|
|
24044
|
-
"none"
|
|
24052
|
+
"none",
|
|
24053
|
+
"unknown"
|
|
24045
24054
|
]),
|
|
24046
24055
|
/**
|
|
24047
24056
|
* True when the camera firmware has gone into low-power mode. Battery
|
|
@@ -24131,7 +24140,7 @@ onStatusChanged: { data: object({
|
|
|
24131
24140
|
kind: "push",
|
|
24132
24141
|
empty: {
|
|
24133
24142
|
percentage: 0,
|
|
24134
|
-
charging: "
|
|
24143
|
+
charging: "unknown",
|
|
24135
24144
|
sleeping: false,
|
|
24136
24145
|
lastUpdated: 0
|
|
24137
24146
|
}
|
|
@@ -33556,8 +33565,17 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
33556
33565
|
async onRestoreDevices(savedDevices) {
|
|
33557
33566
|
const restored = /* @__PURE__ */ new Set();
|
|
33558
33567
|
const failures = [];
|
|
33568
|
+
const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
|
|
33559
33569
|
const attemptRestore = async (saved) => {
|
|
33560
33570
|
if (restored.has(saved.id)) return;
|
|
33571
|
+
if (liveStableIds.has(saved.stableId)) {
|
|
33572
|
+
this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
|
|
33573
|
+
deviceId: saved.id,
|
|
33574
|
+
stableId: saved.stableId
|
|
33575
|
+
} });
|
|
33576
|
+
restored.add(saved.id);
|
|
33577
|
+
return;
|
|
33578
|
+
}
|
|
33561
33579
|
const Class = this.deviceClasses[saved.type];
|
|
33562
33580
|
if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
|
|
33563
33581
|
if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
|
|
@@ -7756,7 +7756,8 @@ var CameraSwitchAuthoritySchema = discriminatedUnion("kind", [
|
|
|
7756
7756
|
var CameraSwitchUnavailableReasonSchema = _enum([
|
|
7757
7757
|
"no-provider",
|
|
7758
7758
|
"source-unreachable",
|
|
7759
|
-
"not-configured"
|
|
7759
|
+
"not-configured",
|
|
7760
|
+
"device-disabled"
|
|
7760
7761
|
]);
|
|
7761
7762
|
/**
|
|
7762
7763
|
* One switch, resolved for one camera.
|
|
@@ -24036,12 +24037,20 @@ var BatteryStatusSchema = object({
|
|
|
24036
24037
|
* Charging source. `'dc'` covers wall/USB adapters; `'solar'` is
|
|
24037
24038
|
* Reolink-specific for the Solar Panel 2 accessory (will become
|
|
24038
24039
|
* common on other battery cams). `'none'` means running on battery
|
|
24039
|
-
* alone.
|
|
24040
|
+
* alone — a NEGATIVE the firmware actually reported.
|
|
24041
|
+
*
|
|
24042
|
+
* `'unknown'` is the absence of an answer: the provider has not read the
|
|
24043
|
+
* power fields yet, or the firmware reported neither. Before it existed,
|
|
24044
|
+
* two unreadable fields produced `'none'`, and a camera nobody had reached
|
|
24045
|
+
* was drawn "on battery alone" — the same D315 defect `percentage` closed
|
|
24046
|
+
* by going nullable. Consumers SKIP it (no charger state published, no
|
|
24047
|
+
* glyph, no HomeKit ChargingState) rather than coerce it either way.
|
|
24040
24048
|
*/
|
|
24041
24049
|
charging: _enum([
|
|
24042
24050
|
"dc",
|
|
24043
24051
|
"solar",
|
|
24044
|
-
"none"
|
|
24052
|
+
"none",
|
|
24053
|
+
"unknown"
|
|
24045
24054
|
]),
|
|
24046
24055
|
/**
|
|
24047
24056
|
* True when the camera firmware has gone into low-power mode. Battery
|
|
@@ -24131,7 +24140,7 @@ onStatusChanged: { data: object({
|
|
|
24131
24140
|
kind: "push",
|
|
24132
24141
|
empty: {
|
|
24133
24142
|
percentage: 0,
|
|
24134
|
-
charging: "
|
|
24143
|
+
charging: "unknown",
|
|
24135
24144
|
sleeping: false,
|
|
24136
24145
|
lastUpdated: 0
|
|
24137
24146
|
}
|
|
@@ -33556,8 +33565,17 @@ var BaseDeviceProvider = class extends BaseAddon {
|
|
|
33556
33565
|
async onRestoreDevices(savedDevices) {
|
|
33557
33566
|
const restored = /* @__PURE__ */ new Set();
|
|
33558
33567
|
const failures = [];
|
|
33568
|
+
const liveStableIds = new Set((await this.ctx.kernel.devices.getAll()).map((device) => device.stableId));
|
|
33559
33569
|
const attemptRestore = async (saved) => {
|
|
33560
33570
|
if (restored.has(saved.id)) return;
|
|
33571
|
+
if (liveStableIds.has(saved.stableId)) {
|
|
33572
|
+
this.ctx.logger.debug("Restore row already live — not dialled again", { tags: {
|
|
33573
|
+
deviceId: saved.id,
|
|
33574
|
+
stableId: saved.stableId
|
|
33575
|
+
} });
|
|
33576
|
+
restored.add(saved.id);
|
|
33577
|
+
return;
|
|
33578
|
+
}
|
|
33561
33579
|
const Class = this.deviceClasses[saved.type];
|
|
33562
33580
|
if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
|
|
33563
33581
|
if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
//#endregion
|
|
6
|
-
const require_dist = require("../dist-
|
|
6
|
+
const require_dist = require("../dist-GeeaZrMS.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
//#region src/ha-export/topics.ts
|
|
9
9
|
/**
|
|
@@ -4959,12 +4959,13 @@ function projectZoneOccupancy(deviceKey, input) {
|
|
|
4959
4959
|
}
|
|
4960
4960
|
function projectBatterySlice(deviceKey, slice) {
|
|
4961
4961
|
const values = [{
|
|
4962
|
-
topic: stateTopic(deviceKey, "charger"),
|
|
4963
|
-
value: bool(slice.charging !== "none")
|
|
4964
|
-
}, {
|
|
4965
4962
|
topic: stateTopic(deviceKey, "sleeping"),
|
|
4966
4963
|
value: bool(slice.sleeping)
|
|
4967
4964
|
}];
|
|
4965
|
+
if (slice.charging !== "unknown") values.push({
|
|
4966
|
+
topic: stateTopic(deviceKey, "charger"),
|
|
4967
|
+
value: bool(slice.charging !== "none")
|
|
4968
|
+
});
|
|
4968
4969
|
/**
|
|
4969
4970
|
* `binary: true` means the device reports "low" or "not low" and the
|
|
4970
4971
|
* percentage is a stand-in. Publishing it would put a fabricated
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-
|
|
1
|
+
import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-ru9DzHlP.mjs";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
3
|
//#region src/ha-export/topics.ts
|
|
4
4
|
/**
|
|
@@ -4954,12 +4954,13 @@ function projectZoneOccupancy(deviceKey, input) {
|
|
|
4954
4954
|
}
|
|
4955
4955
|
function projectBatterySlice(deviceKey, slice) {
|
|
4956
4956
|
const values = [{
|
|
4957
|
-
topic: stateTopic(deviceKey, "charger"),
|
|
4958
|
-
value: bool(slice.charging !== "none")
|
|
4959
|
-
}, {
|
|
4960
4957
|
topic: stateTopic(deviceKey, "sleeping"),
|
|
4961
4958
|
value: bool(slice.sleeping)
|
|
4962
4959
|
}];
|
|
4960
|
+
if (slice.charging !== "unknown") values.push({
|
|
4961
|
+
topic: stateTopic(deviceKey, "charger"),
|
|
4962
|
+
value: bool(slice.charging !== "none")
|
|
4963
|
+
});
|
|
4963
4964
|
/**
|
|
4964
4965
|
* `binary: true` means the device reports "low" or "not low" and the
|
|
4965
4966
|
* percentage is a stand-in. Publishing it would put a fabricated
|