homebridge-tydom-mk 1.0.0 → 1.1.0
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/README.md
CHANGED
|
@@ -165,12 +165,18 @@ They take precedence over the corresponding config fields.
|
|
|
165
165
|
| `settings` | `Record<deviceId, object>` | `{}` | Per-device overrides. See [Device settings](#device-settings). |
|
|
166
166
|
| `debug` | `boolean` | `false` | Log every gateway request and every characteristic read and write. |
|
|
167
167
|
|
|
168
|
-
Device ids are printed in the Homebridge log at startup:
|
|
168
|
+
Device ids are printed in the Homebridge log at startup, one line per accessory:
|
|
169
169
|
|
|
170
170
|
```text
|
|
171
|
-
[Tydom]
|
|
171
|
+
[Tydom] Gateway reports 2 devices, exposing 2 accessories to HomeKit:
|
|
172
|
+
[Tydom] window-covering Kitchen id 1234567
|
|
173
|
+
[Tydom] window-covering Living room id 1234568 new
|
|
174
|
+
[Tydom] Ready: 2 accessories (1 new, 1 up to date)
|
|
172
175
|
```
|
|
173
176
|
|
|
177
|
+
A device the plugin cannot expose is named on a `Not exposed:` line, with its
|
|
178
|
+
Tydom usage and id, so you can tell what is missing and ask for it.
|
|
179
|
+
|
|
174
180
|
Environment variables:
|
|
175
181
|
|
|
176
182
|
| Variable | Description |
|
|
@@ -278,6 +284,8 @@ Reported working by the community:
|
|
|
278
284
|
|
|
279
285
|
- Window coverings ([TYXIA 5630](https://www.deltadore.co.uk/home-automation/control-shutters-blinds-gate-garage/receiver-micromodule/tyxia-5630-ref-6351401), [TYXIA 5730](https://www.deltadore.co.uk/home-automation/control-shutters-blinds-gate-garage/receiver-micromodule/tyxia-5730-ref-6351402), [TYXIA 5731](https://www.deltadore.co.uk/home-automation/control-shutters-blinds-gate-garage/receiver-micromodule/tyxia-5731-ref-6351412))
|
|
280
286
|
|
|
287
|
+
The gateway's weather source, which the gateway lists as `Invisible 1` with no picture, appears as a temperature sensor named "Outdoor weather" ("Météo extérieure" with `locale` set to `fr`). Only the outdoor temperature is exposed: HomeKit has no weather service, and the daily maximum and the irradiation values do not map to one. The name and the missing picture suggest an internal weather service rather than a probe on your façade, so do not expect the reading of a sensor you installed. Rename it with `settings.<deviceId>.name`, or leave it out with `excludedDevices`.
|
|
288
|
+
|
|
281
289
|
Also published: outlets, garage door openers, smoke detectors and temperature sensors. Devices are matched on the shape of the metadata the gateway reports, so similar hardware generally works untouched — and adding a new match is a small change, so please open an issue if yours is not recognised.
|
|
282
290
|
|
|
283
291
|
## Switching from homebridge-tydom
|
package/config.schema.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"pluginType": "platform",
|
|
4
4
|
"singular": true,
|
|
5
5
|
"headerDisplay": "Exposes [Delta Dore](https://www.deltadore.fr/) hardware to HomeKit through a **Tydom** gateway. Lights, shutters, thermostats, garage doors, contact and smoke sensors and Tyxal alarms are discovered automatically — nothing has to be listed by hand.",
|
|
6
|
-
"footerDisplay": "Per-device options live under **Device settings**, keyed by the numeric device id shown in the Homebridge log at startup (`Found new tydom device ... with deviceId=1234567`). Full reference in the [wiki](https://github.com/mgcrea/homebridge-tydom/wiki/Configuration).",
|
|
6
|
+
"footerDisplay": "Per-device options live under **Device settings**, keyed by the numeric device id shown in the Homebridge log at startup (`Found new tydom device ... with deviceId=1234567`). Full reference in the [README](https://github.com/maximekduval/homebridge-tydom#device-settings) and the [upstream wiki](https://github.com/mgcrea/homebridge-tydom/wiki/Configuration).",
|
|
7
7
|
"schema": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"properties": {
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as PLUGIN_NAME, t as PLATFORM_NAME } from "./env-Czc5jJOI.mjs";
|
|
2
2
|
// src/index.ts
|
|
3
3
|
process.setSourceMapsEnabled(true);
|
|
4
|
-
const { default: TydomPlatform } = await import("./platform-
|
|
4
|
+
const { default: TydomPlatform } = await import("./platform-Co0jggka.mjs");
|
|
5
5
|
var src_default = (homebridge) => {
|
|
6
6
|
homebridge.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, TydomPlatform);
|
|
7
7
|
};
|
|
@@ -375,6 +375,10 @@ const FIRST_USAGE_MATCHES = {
|
|
|
375
375
|
deviceType: "window-covering",
|
|
376
376
|
category: CATEGORY.WINDOW_COVERING
|
|
377
377
|
},
|
|
378
|
+
weather: {
|
|
379
|
+
deviceType: "temperature-sensor",
|
|
380
|
+
category: CATEGORY.SENSOR
|
|
381
|
+
},
|
|
378
382
|
window: {
|
|
379
383
|
deviceType: "contact-sensor",
|
|
380
384
|
category: CATEGORY.WINDOW
|
|
@@ -1236,6 +1240,7 @@ const TABLES = {
|
|
|
1236
1240
|
PILE_FAULT_REPETITION: "Battery error",
|
|
1237
1241
|
PIN_FAULT: "PIN code error",
|
|
1238
1242
|
PLAY_ROOM: "Play room",
|
|
1243
|
+
PLUGIN_OUTDOOR_WEATHER: "Outdoor weather",
|
|
1239
1244
|
POOL: "Pool",
|
|
1240
1245
|
PORCH: "Porch",
|
|
1241
1246
|
PRACTICE: "Practice",
|
|
@@ -2256,6 +2261,7 @@ const TABLES = {
|
|
|
2256
2261
|
PILE_FAULT_REPETITION: "Défaut pile",
|
|
2257
2262
|
PIN_FAULT: "Défaut code PIN",
|
|
2258
2263
|
PLAY_ROOM: "Salle de jeux",
|
|
2264
|
+
PLUGIN_OUTDOOR_WEATHER: "Météo extérieure",
|
|
2259
2265
|
POOL: "Piscine",
|
|
2260
2266
|
PORCH: "Porche",
|
|
2261
2267
|
PRACTICE: "Cabinet",
|
|
@@ -2730,6 +2736,62 @@ const createPluginLogger = (log, verbose) => ({
|
|
|
2730
2736
|
log.error(message);
|
|
2731
2737
|
}
|
|
2732
2738
|
});
|
|
2739
|
+
// src/platform/startup-report.ts
|
|
2740
|
+
const count = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
2741
|
+
const statusMarker = (status) => {
|
|
2742
|
+
switch (status) {
|
|
2743
|
+
case "new": return ` ${styleGet("new")}`;
|
|
2744
|
+
case "recreated": return ` ${styleUpd("recreated")}`;
|
|
2745
|
+
default: return "";
|
|
2746
|
+
}
|
|
2747
|
+
};
|
|
2748
|
+
/**
|
|
2749
|
+
* The device list, as the lines to log at info level.
|
|
2750
|
+
*
|
|
2751
|
+
* One line per accessory with its `deviceId`, which `includedDevices` and
|
|
2752
|
+
* `settings` are keyed by and which users have no other way to read. What the
|
|
2753
|
+
* plugin left out is named, rather than reported by `firstUsage` alone: a
|
|
2754
|
+
* missing accessory should be explained by the log, not found by elimination.
|
|
2755
|
+
*/
|
|
2756
|
+
const deviceTableLines = (rows, scan) => {
|
|
2757
|
+
const exposed = count(rows.length, "accessory", "accessories");
|
|
2758
|
+
const colon = rows.length > 0 ? ":" : "";
|
|
2759
|
+
const unsupported = scan?.skipped.filter(({ reason }) => reason === "unsupported") ?? [];
|
|
2760
|
+
const lines = [];
|
|
2761
|
+
if (scan) {
|
|
2762
|
+
const notes = [];
|
|
2763
|
+
if (unsupported.length > 0) notes.push(`${unsupported.length} not supported`);
|
|
2764
|
+
const excluded = scan.skipped.length - unsupported.length;
|
|
2765
|
+
if (excluded > 0) notes.push(`${excluded} excluded by your settings`);
|
|
2766
|
+
const detail = notes.length > 0 ? ` (${notes.join(", ")})` : "";
|
|
2767
|
+
lines.push(`Gateway reports ${count(scan.total, "device")}${detail}, exposing ${exposed} to HomeKit${colon}`);
|
|
2768
|
+
} else lines.push(`Exposing ${exposed} to HomeKit${colon}`);
|
|
2769
|
+
const typeWidth = Math.max(0, ...rows.map(({ type }) => type.length));
|
|
2770
|
+
const nameWidth = Math.max(0, ...rows.map(({ name }) => name.length));
|
|
2771
|
+
for (const { type, name, deviceId, status } of rows) lines.push(` ${styleKeyword(type.padEnd(typeWidth))} ${name.padEnd(nameWidth)} id ${styleNumber(deviceId)}${statusMarker(status)}`);
|
|
2772
|
+
for (const { name, firstUsage, deviceId } of unsupported) lines.push(`Not exposed: ${name} (${firstUsage}, id ${styleNumber(deviceId)}), this type of device is not supported yet`);
|
|
2773
|
+
return lines;
|
|
2774
|
+
};
|
|
2775
|
+
/**
|
|
2776
|
+
* The closing line: how many accessories are live, and what changed.
|
|
2777
|
+
*
|
|
2778
|
+
* An unchanged home reads "all up to date" rather than a row of zeros, so a
|
|
2779
|
+
* restart that changed something stands out from one that did not.
|
|
2780
|
+
*/
|
|
2781
|
+
const readyLine = (ready, rows, removed) => {
|
|
2782
|
+
const created = rows.filter(({ status }) => status === "new").length;
|
|
2783
|
+
const recreated = rows.filter(({ status }) => status === "recreated").length;
|
|
2784
|
+
const known = rows.filter(({ status }) => status === "known").length;
|
|
2785
|
+
const changes = [
|
|
2786
|
+
created > 0 ? `${created} new` : "",
|
|
2787
|
+
recreated > 0 ? `${recreated} recreated` : "",
|
|
2788
|
+
removed > 0 ? `${removed} removed` : ""
|
|
2789
|
+
].filter(Boolean);
|
|
2790
|
+
const accessories = count(ready, "accessory", "accessories");
|
|
2791
|
+
if (changes.length === 0) return `Ready: ${accessories}, all up to date`;
|
|
2792
|
+
if (known > 0) changes.push(`${known} up to date`);
|
|
2793
|
+
return `Ready: ${accessories} (${changes.join(", ")})`;
|
|
2794
|
+
};
|
|
2733
2795
|
// src/util/basic.ts
|
|
2734
2796
|
const stringIncludes = (array, value) => array.includes(value) || array.includes(`${value}`);
|
|
2735
2797
|
/**
|
|
@@ -2822,6 +2884,7 @@ const discoverDevices = (input) => {
|
|
|
2822
2884
|
skipped.push({
|
|
2823
2885
|
deviceId,
|
|
2824
2886
|
endpointId,
|
|
2887
|
+
name: deviceName,
|
|
2825
2888
|
firstUsage,
|
|
2826
2889
|
reason: "filtered"
|
|
2827
2890
|
});
|
|
@@ -2831,6 +2894,7 @@ const discoverDevices = (input) => {
|
|
|
2831
2894
|
skipped.push({
|
|
2832
2895
|
deviceId,
|
|
2833
2896
|
endpointId,
|
|
2897
|
+
name: deviceName,
|
|
2834
2898
|
firstUsage,
|
|
2835
2899
|
reason: "filtered"
|
|
2836
2900
|
});
|
|
@@ -2857,6 +2921,7 @@ const discoverDevices = (input) => {
|
|
|
2857
2921
|
skipped.push({
|
|
2858
2922
|
deviceId,
|
|
2859
2923
|
endpointId,
|
|
2924
|
+
name: deviceName,
|
|
2860
2925
|
firstUsage,
|
|
2861
2926
|
reason: "unsupported"
|
|
2862
2927
|
});
|
|
@@ -2867,6 +2932,7 @@ const discoverDevices = (input) => {
|
|
|
2867
2932
|
skipped.push({
|
|
2868
2933
|
deviceId,
|
|
2869
2934
|
endpointId,
|
|
2935
|
+
name: deviceName,
|
|
2870
2936
|
firstUsage,
|
|
2871
2937
|
reason: "filtered"
|
|
2872
2938
|
});
|
|
@@ -2876,6 +2942,7 @@ const discoverDevices = (input) => {
|
|
|
2876
2942
|
skipped.push({
|
|
2877
2943
|
deviceId,
|
|
2878
2944
|
endpointId,
|
|
2945
|
+
name: deviceName,
|
|
2879
2946
|
firstUsage,
|
|
2880
2947
|
reason: "filtered"
|
|
2881
2948
|
});
|
|
@@ -3344,6 +3411,14 @@ var TydomController = class extends EventEmitter {
|
|
|
3344
3411
|
* companion, since the primary always claimed the key first.
|
|
3345
3412
|
*/
|
|
3346
3413
|
emitted = /* @__PURE__ */ new Set();
|
|
3414
|
+
/**
|
|
3415
|
+
* What the last completed scan found, including the endpoints it left out.
|
|
3416
|
+
*
|
|
3417
|
+
* A property rather than the return value of `scan`, which announces the
|
|
3418
|
+
* devices through events: the platform reads it once the announced devices
|
|
3419
|
+
* have settled, to report them together.
|
|
3420
|
+
*/
|
|
3421
|
+
lastScan;
|
|
3347
3422
|
refreshInterval;
|
|
3348
3423
|
hasConnectedOnce = false;
|
|
3349
3424
|
/**
|
|
@@ -3392,7 +3467,7 @@ var TydomController = class extends EventEmitter {
|
|
|
3392
3467
|
this.log = log;
|
|
3393
3468
|
this.t = createTranslator(config.locale);
|
|
3394
3469
|
const { hostname, username, password, email } = config;
|
|
3395
|
-
|
|
3470
|
+
debug(`Creating tydom client with username=${styleString(username)} and hostname=${styleString(hostname)}`);
|
|
3396
3471
|
this.gatewayPassword = email ? "" : password;
|
|
3397
3472
|
this.client = this.createClient(this.gatewayPassword);
|
|
3398
3473
|
}
|
|
@@ -3431,7 +3506,7 @@ var TydomController = class extends EventEmitter {
|
|
|
3431
3506
|
this.resync().catch((err) => {
|
|
3432
3507
|
this.log.error(`Failed to re-sync after reconnection: ${stringifyError(err)}`);
|
|
3433
3508
|
});
|
|
3434
|
-
} else this.log.info(`
|
|
3509
|
+
} else this.log.info(`Connected to Tydom gateway ${styleString(username)} via ${styleString(hostname)}`);
|
|
3435
3510
|
this.emit("connect");
|
|
3436
3511
|
});
|
|
3437
3512
|
client.on("disconnect", () => {
|
|
@@ -3540,7 +3615,7 @@ var TydomController = class extends EventEmitter {
|
|
|
3540
3615
|
this.gatewayPassword = password;
|
|
3541
3616
|
this.client.removeAllListeners();
|
|
3542
3617
|
this.client = this.createClient(password);
|
|
3543
|
-
this.log.info(`
|
|
3618
|
+
this.log.info(`Got the password of gateway ${styleString(username)} from your Delta Dore account`);
|
|
3544
3619
|
}
|
|
3545
3620
|
/** Whether a socket is up, however it got there. */
|
|
3546
3621
|
get isConnected() {
|
|
@@ -3590,7 +3665,8 @@ var TydomController = class extends EventEmitter {
|
|
|
3590
3665
|
}
|
|
3591
3666
|
async scan() {
|
|
3592
3667
|
const { hostname, username, settings = {} } = this.config;
|
|
3593
|
-
this.log.info(
|
|
3668
|
+
this.log.info("Reading the device list...");
|
|
3669
|
+
debug(`Scanning devices from hostname=${styleString(hostname)}...`);
|
|
3594
3670
|
const { config, groups, meta, cmeta } = await this.sync();
|
|
3595
3671
|
const { devices, skipped } = discoverDevices({
|
|
3596
3672
|
username,
|
|
@@ -3606,16 +3682,18 @@ var TydomController = class extends EventEmitter {
|
|
|
3606
3682
|
excludedCategories: this.config.excludedCategories
|
|
3607
3683
|
}
|
|
3608
3684
|
});
|
|
3609
|
-
|
|
3685
|
+
this.lastScan = {
|
|
3686
|
+
total: config.endpoints.length,
|
|
3687
|
+
skipped
|
|
3688
|
+
};
|
|
3610
3689
|
for (const device of devices.flatMap((d) => expandCompanions(d))) {
|
|
3611
3690
|
const { uniqueId, deviceId, endpointId, firstUsage, category } = device;
|
|
3612
|
-
this.log.info(`Found new device with firstUsage=${styleString(firstUsage)}, deviceId=${styleNumber(deviceId)} and endpointId=${styleNumber(endpointId)}`);
|
|
3613
3691
|
if (this.emitted.has(device.accessoryId)) continue;
|
|
3614
3692
|
this.emitted.add(device.accessoryId);
|
|
3615
|
-
|
|
3693
|
+
debug(`Announcing device with firstUsage=${styleString(firstUsage)}, deviceId=${styleNumber(deviceId)} and endpointId=${styleNumber(endpointId)}`);
|
|
3616
3694
|
if (!device.companionOf) this.devices.set(uniqueId, category);
|
|
3617
3695
|
const context = {
|
|
3618
|
-
name:
|
|
3696
|
+
name: this.accessoryName(device),
|
|
3619
3697
|
category,
|
|
3620
3698
|
deviceType: device.deviceType,
|
|
3621
3699
|
metadata: device.metadata,
|
|
@@ -3633,6 +3711,17 @@ var TydomController = class extends EventEmitter {
|
|
|
3633
3711
|
this.emit("device", context);
|
|
3634
3712
|
}
|
|
3635
3713
|
}
|
|
3714
|
+
/**
|
|
3715
|
+
* The name an accessory is announced under.
|
|
3716
|
+
*
|
|
3717
|
+
* Discovery stays framework-free, so the names that come from the locale
|
|
3718
|
+
* tables are filled in here. A name the user set in `settings` always wins.
|
|
3719
|
+
*/
|
|
3720
|
+
accessoryName(device) {
|
|
3721
|
+
if (device.deviceType === "alarm-sensors") return this.t("ALARME_ISSUES_OUVERTES", device.name);
|
|
3722
|
+
if (device.firstUsage === "weather" && device.settings.name === void 0) return this.t("PLUGIN_OUTDOOR_WEATHER", device.name);
|
|
3723
|
+
return device.name;
|
|
3724
|
+
}
|
|
3636
3725
|
async refresh() {
|
|
3637
3726
|
debug(`Refreshing Tydom controller ...`);
|
|
3638
3727
|
await this.client.post("/refresh/all");
|
|
@@ -5738,6 +5827,11 @@ var TydomPlatform = class {
|
|
|
5738
5827
|
* told us nothing", and those look identical from the cleanup set alone.
|
|
5739
5828
|
*/
|
|
5740
5829
|
discoveredDevices = 0;
|
|
5830
|
+
/**
|
|
5831
|
+
* One row per accessory the current scan announced, in the order the gateway
|
|
5832
|
+
* listed them, for the device list logged once the scan has settled.
|
|
5833
|
+
*/
|
|
5834
|
+
startupRows = [];
|
|
5741
5835
|
accessories = /* @__PURE__ */ new Map();
|
|
5742
5836
|
/** Live handlers, keyed by the same UUID as `accessories`. */
|
|
5743
5837
|
handlers = /* @__PURE__ */ new Map();
|
|
@@ -5843,6 +5937,8 @@ var TydomPlatform = class {
|
|
|
5843
5937
|
assert(this.controller);
|
|
5844
5938
|
this.cleanupAccessoriesIds = new Set(this.accessories.keys());
|
|
5845
5939
|
this.discoveredDevices = 0;
|
|
5940
|
+
this.startupRows = [];
|
|
5941
|
+
this.controller.lastScan = void 0;
|
|
5846
5942
|
const maxDelay = 3e5;
|
|
5847
5943
|
for (let attempt = 0;; attempt++) {
|
|
5848
5944
|
if (this.shuttingDown) return;
|
|
@@ -5862,19 +5958,34 @@ var TydomPlatform = class {
|
|
|
5862
5958
|
}
|
|
5863
5959
|
}
|
|
5864
5960
|
await this.settlePendingDevices();
|
|
5961
|
+
const rows = this.startupRows.filter(({ id }) => this.accessories.has(id));
|
|
5962
|
+
this.logDeviceList(rows);
|
|
5865
5963
|
if (this.discoveredDevices === 0 && this.accessories.size > 0) {
|
|
5866
5964
|
this.log.warn(`The gateway reported no devices, so the ${this.accessories.size} known accessories were kept rather than deleted. This is usually a gateway that is still starting up, or one whose radio is down — check it answers in the Tydom app, then restart Homebridge. Remove them from the Homebridge UI if they really are gone.`);
|
|
5867
|
-
this.log.info(`
|
|
5965
|
+
this.log.info(`Ready: ${this.accessories.size} kept from the previous run, none confirmed by the gateway`);
|
|
5868
5966
|
return;
|
|
5869
5967
|
}
|
|
5968
|
+
let removed = 0;
|
|
5870
5969
|
this.cleanupAccessoriesIds.forEach((accessoryId) => {
|
|
5871
5970
|
const accessory = this.accessories.get(accessoryId);
|
|
5872
5971
|
if (!accessory) return;
|
|
5873
|
-
this.log.warn(`
|
|
5972
|
+
this.log.warn(`Removing ${styleString(accessory.displayName)} (id ${styleNumber(accessory.context.deviceId)}): the gateway no longer reports it`);
|
|
5874
5973
|
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
5875
5974
|
this.forgetAccessory(accessoryId);
|
|
5975
|
+
removed += 1;
|
|
5876
5976
|
});
|
|
5877
|
-
this.log.info(
|
|
5977
|
+
this.log.info(readyLine(this.accessories.size, rows, removed));
|
|
5978
|
+
}
|
|
5979
|
+
/**
|
|
5980
|
+
* Log what the gateway reported and what is now exposed to HomeKit.
|
|
5981
|
+
*
|
|
5982
|
+
* The one place devices show up at info level, as one line each: the platform
|
|
5983
|
+
* used to log four per accessory, and in no order a reader could follow.
|
|
5984
|
+
*/
|
|
5985
|
+
logDeviceList(rows) {
|
|
5986
|
+
const scan = this.controller?.lastScan;
|
|
5987
|
+
for (const line of deviceTableLines(rows, scan)) this.log.info(line);
|
|
5988
|
+
for (const { name, deviceId, firstUsage, reason } of scan?.skipped ?? []) if (reason === "filtered") this.log.debug(`Excluded by your settings: ${styleString(name)} (firstUsage=${styleString(firstUsage)}, deviceId=${styleNumber(deviceId)})`);
|
|
5878
5989
|
}
|
|
5879
5990
|
/**
|
|
5880
5991
|
* Open the first connection if there is none yet, then read the device list.
|
|
@@ -5927,11 +6038,20 @@ var TydomPlatform = class {
|
|
|
5927
6038
|
async handleControllerDevice(context) {
|
|
5928
6039
|
const { name, deviceId, category, accessoryId } = context;
|
|
5929
6040
|
const id = this.api.hap.uuid.generate(accessoryId);
|
|
5930
|
-
this.log.
|
|
5931
|
-
this.log.debug(`Tydom with deviceId=${styleNumber(deviceId)} (id=${styleKeyword(id)}) context="${JSON.stringify(context)}"`);
|
|
6041
|
+
this.log.debug(`Tydom device named=${styleString(name)} with deviceId=${styleNumber(deviceId)} (id=${styleKeyword(id)}) context="${JSON.stringify(context)}"`);
|
|
5932
6042
|
const existingAccessory = this.accessories.get(id);
|
|
5933
6043
|
const hasNewCategory = existingAccessory?.category !== category;
|
|
5934
6044
|
debug(`[${deviceId}] ${existingAccessory?.category} vs ${category}`);
|
|
6045
|
+
let status = "known";
|
|
6046
|
+
if (!existingAccessory) status = "new";
|
|
6047
|
+
else if (hasNewCategory) status = "recreated";
|
|
6048
|
+
this.startupRows.push({
|
|
6049
|
+
id,
|
|
6050
|
+
type: this.resolveDeviceType(context, category) ?? "unknown",
|
|
6051
|
+
name: existingAccessory && !hasNewCategory ? existingAccessory.displayName : this.accessoryNameFor(name, category, context.group),
|
|
6052
|
+
deviceId,
|
|
6053
|
+
status
|
|
6054
|
+
});
|
|
5935
6055
|
this.discoveredDevices += 1;
|
|
5936
6056
|
this.cleanupAccessoriesIds.delete(id);
|
|
5937
6057
|
if (existingAccessory) {
|
|
@@ -5939,7 +6059,7 @@ var TydomPlatform = class {
|
|
|
5939
6059
|
await this.updateAccessory(existingAccessory, context);
|
|
5940
6060
|
return;
|
|
5941
6061
|
} else {
|
|
5942
|
-
this.log.warn(`
|
|
6062
|
+
this.log.warn(`Recreating ${styleString(existingAccessory.displayName)} (id ${styleNumber(deviceId)}): its HomeKit category changed`);
|
|
5943
6063
|
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
|
|
5944
6064
|
this.forgetAccessory(id, { pruneCompanions: false });
|
|
5945
6065
|
}
|
|
@@ -5985,11 +6105,14 @@ var TydomPlatform = class {
|
|
|
5985
6105
|
resolveDeviceType(context, category) {
|
|
5986
6106
|
return context.deviceType ?? deviceTypeForCategory(category, context.settings, context.metadata);
|
|
5987
6107
|
}
|
|
6108
|
+
/** The HomeKit name of a new accessory: a window takes the name of its group. */
|
|
6109
|
+
accessoryNameFor(name, category, group) {
|
|
6110
|
+
return category === CATEGORY.WINDOW && group ? group.name || name : name;
|
|
6111
|
+
}
|
|
5988
6112
|
async createAccessory(name, id, category, context) {
|
|
5989
6113
|
const { platformAccessory: PlatformAccessory } = this.api;
|
|
5990
|
-
const
|
|
5991
|
-
|
|
5992
|
-
this.log.info(`Creating accessory named=${styleString(accessoryName)}, deviceId="${styleNumber(context.deviceId)} (id=${styleKeyword(id)})"`);
|
|
6114
|
+
const accessoryName = this.accessoryNameFor(name, category, context.group);
|
|
6115
|
+
this.log.debug(`Creating accessory named=${styleString(accessoryName)}, deviceId=${styleNumber(context.deviceId)} (id=${styleKeyword(id)})`);
|
|
5993
6116
|
const accessory = new PlatformAccessory(accessoryName, id, category);
|
|
5994
6117
|
Object.assign(accessory.context, context);
|
|
5995
6118
|
return accessory;
|
|
@@ -6004,7 +6127,7 @@ var TydomPlatform = class {
|
|
|
6004
6127
|
*/
|
|
6005
6128
|
async updateAccessory(accessory, context) {
|
|
6006
6129
|
const { displayName: accessoryName, UUID: id } = accessory;
|
|
6007
|
-
this.log.
|
|
6130
|
+
this.log.debug(`Updating accessory named=${styleString(accessoryName)}, deviceId=${styleNumber(context.deviceId)} (id=${styleKeyword(id)})`);
|
|
6008
6131
|
if (!await this.configureHandler(accessory, context)) return;
|
|
6009
6132
|
this.api.updatePlatformAccessories([accessory]);
|
|
6010
6133
|
}
|
|
@@ -6051,4 +6174,4 @@ var TydomPlatform = class {
|
|
|
6051
6174
|
};
|
|
6052
6175
|
export { TydomPlatform as default };
|
|
6053
6176
|
|
|
6054
|
-
//# sourceMappingURL=platform-
|
|
6177
|
+
//# sourceMappingURL=platform-Co0jggka.mjs.map
|