homebridge-tydom 0.32.1 → 0.32.3
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/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as PLUGIN_NAME, t as PLATFORM_NAME } from "./env-B2-Dw8C2.mjs";
|
|
2
2
|
//#region src/index.ts
|
|
3
3
|
process.setSourceMapsEnabled(true);
|
|
4
|
-
const { default: TydomPlatform } = await import("./platform-
|
|
4
|
+
const { default: TydomPlatform } = await import("./platform-d-jxZ1Nu.mjs");
|
|
5
5
|
var src_default = (homebridge) => {
|
|
6
6
|
homebridge.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, TydomPlatform);
|
|
7
7
|
};
|
|
@@ -3021,6 +3021,15 @@ const parseDiscoveryResponse = (uri, schema, payload) => {
|
|
|
3021
3021
|
* device is not the shape the accessory was built for — which is a bug in the
|
|
3022
3022
|
* signature table, not a value HomeKit should be handed.
|
|
3023
3023
|
*/
|
|
3024
|
+
/**
|
|
3025
|
+
* The value of a property the hardware may simply not carry.
|
|
3026
|
+
*
|
|
3027
|
+
* `getTydomDataPropValue` asserts, which is right for a property the device
|
|
3028
|
+
* type guarantees. Delta Dore's HVAC range guarantees less than it looks: some
|
|
3029
|
+
* endpoints expose a thermic level and no numbers at all, no `setpoint` and no
|
|
3030
|
+
* `temperature`, and asserting on those turned every read into an error.
|
|
3031
|
+
*/
|
|
3032
|
+
const findTydomDataPropValue = (data, name) => data.find((prop) => prop.name === name)?.value;
|
|
3024
3033
|
const getTydomDataPropValue = (data, name) => {
|
|
3025
3034
|
const item = data.find((prop) => prop.name === name);
|
|
3026
3035
|
assert(item, `Missing property with name="${name}" in endpoint data`);
|
|
@@ -4039,11 +4048,12 @@ var GarageDoorAccessory = class extends BaseAccessory {
|
|
|
4039
4048
|
this.#computedPosition = doorState === CurrentDoorState.OPEN ? 100 : 0;
|
|
4040
4049
|
}
|
|
4041
4050
|
#setDoorState(doorState) {
|
|
4042
|
-
const { CurrentDoorState } = this.platform.Characteristic;
|
|
4051
|
+
const { CurrentDoorState, TargetDoorState } = this.platform.Characteristic;
|
|
4043
4052
|
debug(`assignCurrentDoorState=${styleString(this.#label(doorState))}`);
|
|
4044
4053
|
this.#currentDoorState = doorState;
|
|
4045
4054
|
this.#settleTarget(doorState);
|
|
4046
4055
|
this.#service.updateCharacteristic(CurrentDoorState, doorState);
|
|
4056
|
+
if (doorState === CurrentDoorState.OPEN || doorState === CurrentDoorState.CLOSED) this.#service.updateCharacteristic(TargetDoorState, this.#targetDoorState);
|
|
4047
4057
|
}
|
|
4048
4058
|
/** A door at rest, open or closed, was headed exactly there. */
|
|
4049
4059
|
#settleTarget(doorState) {
|
|
@@ -4381,19 +4391,28 @@ const isZoneArmed = (alarmData, zoneProp) => {
|
|
|
4381
4391
|
if (alarmMode === "ON") return true;
|
|
4382
4392
|
return alarmData.find((prop) => prop.name === zoneProp)?.value === "ON";
|
|
4383
4393
|
};
|
|
4394
|
+
/**
|
|
4395
|
+
* The arming mode a data snapshot describes, ignoring whether the siren is on.
|
|
4396
|
+
*
|
|
4397
|
+
* This is what `SecuritySystemTargetState` asks for, and the reason it cannot
|
|
4398
|
+
* share `getStateForAlarmData`: the target has no `ALARM_TRIGGERED`, so the
|
|
4399
|
+
* return type excludes it and HAP can never be handed a value it would reject.
|
|
4400
|
+
*/
|
|
4401
|
+
const getTargetStateForAlarmData = (alarmData, aliases, settings) => {
|
|
4402
|
+
const alarmMode = alarmData.find((prop) => prop.name === "alarmMode")?.value;
|
|
4403
|
+
if (alarmMode === "ON") return ALARM_STATE.AWAY_ARM;
|
|
4404
|
+
if (typeof alarmMode === "string" && ["ZONE", "PART"].includes(alarmMode)) return getStateForActiveZones(getActiveZones(alarmData, settings), aliases);
|
|
4405
|
+
return ALARM_STATE.DISARMED;
|
|
4406
|
+
};
|
|
4384
4407
|
/** The HomeKit state for a full alarm data snapshot. */
|
|
4385
4408
|
const getStateForAlarmData = (alarmData, aliases, settings) => {
|
|
4386
|
-
const
|
|
4387
|
-
const alarmState = find("alarmState");
|
|
4388
|
-
const alarmMode = find("alarmMode");
|
|
4409
|
+
const alarmState = alarmData.find((prop) => prop.name === "alarmState")?.value;
|
|
4389
4410
|
if (typeof alarmState === "string" && [
|
|
4390
4411
|
"DELAYED",
|
|
4391
4412
|
"ON",
|
|
4392
4413
|
"QUIET"
|
|
4393
4414
|
].includes(alarmState)) return ALARM_STATE.ALARM_TRIGGERED;
|
|
4394
|
-
|
|
4395
|
-
if (typeof alarmMode === "string" && ["ZONE", "PART"].includes(alarmMode)) return getStateForActiveZones(getActiveZones(alarmData, settings), aliases);
|
|
4396
|
-
return ALARM_STATE.DISARMED;
|
|
4415
|
+
return getTargetStateForAlarmData(alarmData, aliases, settings);
|
|
4397
4416
|
};
|
|
4398
4417
|
//#endregion
|
|
4399
4418
|
//#region src/accessories/security-system-accessory.ts
|
|
@@ -4449,7 +4468,7 @@ var SecuritySystemAccessory = class extends BaseAccessory {
|
|
|
4449
4468
|
});
|
|
4450
4469
|
service.getCharacteristic(SecuritySystemTargetState).onGet(async () => {
|
|
4451
4470
|
debugGet(SecuritySystemTargetState, service);
|
|
4452
|
-
const nextValue = await this.#
|
|
4471
|
+
const nextValue = await this.#targetState();
|
|
4453
4472
|
debugGetResult(SecuritySystemTargetState, service, nextValue);
|
|
4454
4473
|
return nextValue;
|
|
4455
4474
|
}).onSet(async (value) => {
|
|
@@ -4475,6 +4494,17 @@ var SecuritySystemAccessory = class extends BaseAccessory {
|
|
|
4475
4494
|
const data = await this.#read();
|
|
4476
4495
|
return getStateForAlarmData(data, this.#settings.aliases ?? {}, this.#settings);
|
|
4477
4496
|
}
|
|
4497
|
+
/**
|
|
4498
|
+
* The mode the panel is set to, which is what the target characteristic asks.
|
|
4499
|
+
*
|
|
4500
|
+
* Deliberately not `#currentState`: that one answers `ALARM_TRIGGERED` while
|
|
4501
|
+
* the siren is going, and the target has no such value, so HAP rejected it.
|
|
4502
|
+
* A ringing alarm says nothing about what the panel was armed to anyway.
|
|
4503
|
+
*/
|
|
4504
|
+
async #targetState() {
|
|
4505
|
+
const data = await this.#read();
|
|
4506
|
+
return getTargetStateForAlarmData(data, this.#settings.aliases ?? {}, this.#settings);
|
|
4507
|
+
}
|
|
4478
4508
|
async #readZoneLabels() {
|
|
4479
4509
|
if (this.#legacy) {
|
|
4480
4510
|
this.platform.log.warn(`Setting up legacy zones`);
|
|
@@ -4562,11 +4592,15 @@ var SecuritySystemAccessory = class extends BaseAccessory {
|
|
|
4562
4592
|
return;
|
|
4563
4593
|
}
|
|
4564
4594
|
const aliases = this.#settings.aliases ?? {};
|
|
4565
|
-
const
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4595
|
+
const isStay = target === SecuritySystemTargetState.STAY_ARM;
|
|
4596
|
+
const alias = isStay ? "stay" : "night";
|
|
4597
|
+
const targetZones = aliases[alias];
|
|
4598
|
+
if (!Array.isArray(targetZones) || targetZones.length === 0) {
|
|
4599
|
+
this.platform.log.warn(`Cannot arm ${this.name} to ${isStay ? "Home" : "Night"}: no zones are configured for that mode, so nothing was sent and the Home app will report the change as failed. Add {"settings": {"${this.deviceId}": {"aliases": {"${alias}": [1]}}}} listing the zones it should arm, numbered as they are on the panel's keypad.`);
|
|
4600
|
+
return;
|
|
4569
4601
|
}
|
|
4602
|
+
await this.#setZones(targetZones, "ON");
|
|
4603
|
+
if (this.#service) debugSetResult(SecuritySystemTargetState, this.#service, target, "ON");
|
|
4570
4604
|
}
|
|
4571
4605
|
async #setZones(zoneIds, value) {
|
|
4572
4606
|
if (!this.#legacy) {
|
|
@@ -4583,15 +4617,12 @@ var SecuritySystemAccessory = class extends BaseAccessory {
|
|
|
4583
4617
|
});
|
|
4584
4618
|
}
|
|
4585
4619
|
#handleData(updates) {
|
|
4586
|
-
const {
|
|
4620
|
+
const { ContactSensorState, On } = this.platform.Characteristic;
|
|
4587
4621
|
const aliases = this.#settings.aliases ?? {};
|
|
4588
4622
|
for (const { name, value } of updates) {
|
|
4589
4623
|
if (name === "alarmMode") {
|
|
4590
4624
|
const nextValue = value === "OFF" ? ALARM_STATE.DISARMED : value === "ON" ? ALARM_STATE.AWAY_ARM : value === "PART" || value === "ZONE" ? getStateForActiveZones(getActiveZones(updates, this.#settings), aliases) : void 0;
|
|
4591
|
-
if (nextValue !== void 0
|
|
4592
|
-
debugSetUpdate(SecuritySystemCurrentState, this.#service, nextValue);
|
|
4593
|
-
this.#service.updateCharacteristic(SecuritySystemCurrentState, nextValue);
|
|
4594
|
-
}
|
|
4625
|
+
if (nextValue !== void 0) this.#setState(nextValue);
|
|
4595
4626
|
if (value === "OFF") this.#syncZoneSwitches([]);
|
|
4596
4627
|
else if (value === "ON") this.#syncZoneSwitches(null);
|
|
4597
4628
|
continue;
|
|
@@ -4669,11 +4700,22 @@ var SecuritySystemAccessory = class extends BaseAccessory {
|
|
|
4669
4700
|
service.updateCharacteristic(On, nextValue);
|
|
4670
4701
|
}
|
|
4671
4702
|
}
|
|
4703
|
+
/**
|
|
4704
|
+
* Settle both arming characteristics from an authoritative mode.
|
|
4705
|
+
*
|
|
4706
|
+
* The target moves with the current state, so that arming from the panel's
|
|
4707
|
+
* own keypad does not leave HomeKit showing the old mode — a stale target is
|
|
4708
|
+
* what makes "arm away" in the Home app look like it did nothing. The
|
|
4709
|
+
* parameter type excludes `ALARM_TRIGGERED`, so the target can never be
|
|
4710
|
+
* handed a value it would reject.
|
|
4711
|
+
*/
|
|
4672
4712
|
#setState(state) {
|
|
4673
4713
|
if (!this.#service) return;
|
|
4674
|
-
const { SecuritySystemCurrentState } = this.platform.Characteristic;
|
|
4714
|
+
const { SecuritySystemCurrentState, SecuritySystemTargetState } = this.platform.Characteristic;
|
|
4675
4715
|
debugSetUpdate(SecuritySystemCurrentState, this.#service, state);
|
|
4676
4716
|
this.#service.updateCharacteristic(SecuritySystemCurrentState, state);
|
|
4717
|
+
debugSetUpdate(SecuritySystemTargetState, this.#service, state);
|
|
4718
|
+
this.#service.updateCharacteristic(SecuritySystemTargetState, state);
|
|
4677
4719
|
}
|
|
4678
4720
|
};
|
|
4679
4721
|
const createSecuritySystemAccessory = (deps) => {
|
|
@@ -4781,6 +4823,14 @@ const EXPOSED_THERMIC_LEVELS = /* @__PURE__ */ new Set([
|
|
|
4781
4823
|
"ECO",
|
|
4782
4824
|
"COMFORT"
|
|
4783
4825
|
]);
|
|
4826
|
+
/**
|
|
4827
|
+
* What to report when the endpoint carries no temperature at all.
|
|
4828
|
+
*
|
|
4829
|
+
* HAP's own default for `CurrentTemperature`, so a device with no thermometer
|
|
4830
|
+
* looks the same as one that has not answered yet, rather than inventing a
|
|
4831
|
+
* reading.
|
|
4832
|
+
*/
|
|
4833
|
+
const UNKNOWN_TEMPERATURE = 0;
|
|
4784
4834
|
/** An electric heating controller (Delta Dore RF4890, RF6600FP). */
|
|
4785
4835
|
var ThermostatAccessory = class extends BaseAccessory {
|
|
4786
4836
|
#service;
|
|
@@ -4827,9 +4877,13 @@ var ThermostatAccessory = class extends BaseAccessory {
|
|
|
4827
4877
|
debugGet(CurrentHeatingCoolingState, this.#service);
|
|
4828
4878
|
const data = await this.#read();
|
|
4829
4879
|
const authorization = getTydomDataPropValue(data, "authorization");
|
|
4830
|
-
const setpoint =
|
|
4831
|
-
const temperature =
|
|
4880
|
+
const setpoint = findTydomDataPropValue(data, "setpoint");
|
|
4881
|
+
const temperature = findTydomDataPropValue(data, "temperature");
|
|
4832
4882
|
let nextValue = CurrentHeatingCoolingState.OFF;
|
|
4883
|
+
if (typeof setpoint !== "number" || typeof temperature !== "number") {
|
|
4884
|
+
debugGetResult(CurrentHeatingCoolingState, this.#service, nextValue);
|
|
4885
|
+
return nextValue;
|
|
4886
|
+
}
|
|
4833
4887
|
if (authorization === "HEATING" && setpoint > temperature) nextValue = CurrentHeatingCoolingState.HEAT;
|
|
4834
4888
|
else if (authorization === "COOLING" && temperature > setpoint) nextValue = CurrentHeatingCoolingState.COOL;
|
|
4835
4889
|
debugGetResult(CurrentHeatingCoolingState, this.#service, nextValue);
|
|
@@ -4869,14 +4923,15 @@ var ThermostatAccessory = class extends BaseAccessory {
|
|
|
4869
4923
|
});
|
|
4870
4924
|
this.#service.getCharacteristic(CurrentTemperature).onGet(async () => {
|
|
4871
4925
|
debugGet(CurrentTemperature, this.#service);
|
|
4872
|
-
const
|
|
4926
|
+
const data = await this.#read();
|
|
4927
|
+
const temperature = findTydomDataPropValue(data, "temperature") ?? findTydomDataPropValue(data, "setpoint") ?? UNKNOWN_TEMPERATURE;
|
|
4873
4928
|
debugGetResult(CurrentTemperature, this.#service, temperature);
|
|
4874
4929
|
return temperature;
|
|
4875
4930
|
});
|
|
4876
4931
|
this.#service.getCharacteristic(TargetTemperature).onGet(async () => {
|
|
4877
4932
|
debugGet(TargetTemperature, this.#service);
|
|
4878
4933
|
const data = await this.#read();
|
|
4879
|
-
const setpoint =
|
|
4934
|
+
const setpoint = findTydomDataPropValue(data, "setpoint") ?? findTydomDataPropValue(data, "temperature") ?? UNKNOWN_TEMPERATURE;
|
|
4880
4935
|
debugGetResult(TargetTemperature, this.#service, setpoint);
|
|
4881
4936
|
return setpoint;
|
|
4882
4937
|
}).onSet(async (value) => {
|
|
@@ -5620,4 +5675,4 @@ var TydomPlatform = class {
|
|
|
5620
5675
|
//#endregion
|
|
5621
5676
|
export { TydomPlatform as default };
|
|
5622
5677
|
|
|
5623
|
-
//# sourceMappingURL=platform-
|
|
5678
|
+
//# sourceMappingURL=platform-d-jxZ1Nu.mjs.map
|