homebridge 2.0.0-alpha.46 → 2.0.0-alpha.48
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/api.d.ts +179 -59
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +26 -50
- package/dist/api.js.map +1 -1
- package/dist/index.d.ts +35 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +6 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +8 -0
- package/dist/logger.js.map +1 -1
- package/dist/matter/index.d.ts +41 -1
- package/dist/matter/index.d.ts.map +1 -1
- package/dist/matter/index.js +1 -1
- package/dist/matter/index.js.map +1 -1
- package/dist/matter/matterAccessoryCache.d.ts +3 -1
- package/dist/matter/matterAccessoryCache.d.ts.map +1 -1
- package/dist/matter/matterAccessoryCache.js +26 -20
- package/dist/matter/matterAccessoryCache.js.map +1 -1
- package/dist/matter/matterBehaviors.d.ts +4 -0
- package/dist/matter/matterBehaviors.d.ts.map +1 -1
- package/dist/matter/matterBehaviors.js +30 -1
- package/dist/matter/matterBehaviors.js.map +1 -1
- package/dist/matter/matterConfigValidator.js +1 -1
- package/dist/matter/matterConfigValidator.js.map +1 -1
- package/dist/matter/matterErrorHandler.js +1 -1
- package/dist/matter/matterErrorHandler.js.map +1 -1
- package/dist/matter/matterLogFormatter.d.ts +18 -0
- package/dist/matter/matterLogFormatter.d.ts.map +1 -0
- package/dist/matter/matterLogFormatter.js +128 -0
- package/dist/matter/matterLogFormatter.js.map +1 -0
- package/dist/matter/matterNetworkMonitor.js +1 -1
- package/dist/matter/matterNetworkMonitor.js.map +1 -1
- package/dist/matter/matterServer.d.ts +6 -4
- package/dist/matter/matterServer.d.ts.map +1 -1
- package/dist/matter/matterServer.js +148 -52
- package/dist/matter/matterServer.js.map +1 -1
- package/dist/matter/matterStorage.js +1 -1
- package/dist/matter/matterTypes.d.ts +37 -1
- package/dist/matter/matterTypes.d.ts.map +1 -1
- package/dist/matter/matterTypes.js +36 -0
- package/dist/matter/matterTypes.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { Logger } from '../logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* Matter.js Log Formatter
|
|
5
|
+
*
|
|
6
|
+
* Formats Matter.js library logs to match the homebridge log format and color scheme.
|
|
7
|
+
* This ensures consistent logging output across Homebridge and Matter.js.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Create a custom log formatter that matches the homebridge format.
|
|
11
|
+
* Format: [DD/MM/YYYY, HH:MM:SS AM/PM] [Matter:Facility] message
|
|
12
|
+
*
|
|
13
|
+
* Log level color mapping:
|
|
14
|
+
* - Matter DEBUG/INFO → gray (Homebridge debug)
|
|
15
|
+
* - Matter NOTICE → no color (Homebridge info)
|
|
16
|
+
* - Matter WARN → yellow (Homebridge warn)
|
|
17
|
+
* - Matter ERROR/FATAL → red (Homebridge error)
|
|
18
|
+
*/
|
|
19
|
+
export function createHomebridgeLogFormatter() {
|
|
20
|
+
// Capture timestamp setting once when formatter is created
|
|
21
|
+
const timestampEnabled = Logger.isTimestampEnabled();
|
|
22
|
+
return (diagnostic) => {
|
|
23
|
+
// Check if this is a Matter.js log message
|
|
24
|
+
if (typeof diagnostic === 'object' && diagnostic !== null) {
|
|
25
|
+
const msg = diagnostic;
|
|
26
|
+
// If it's a log message with the expected structure
|
|
27
|
+
if (msg.now && msg.facility && msg.values) {
|
|
28
|
+
// Format facility as [Matter:FacilityName] in cyan color
|
|
29
|
+
const facility = formatCyan(`[Matter/${msg.facility}]`);
|
|
30
|
+
// Extract the message text from values
|
|
31
|
+
const messageText = formatMessageValues(msg.values);
|
|
32
|
+
// Apply color based on Matter log level
|
|
33
|
+
// Matter DEBUG/INFO → grey (Homebridge debug)
|
|
34
|
+
// Matter NOTICE → no color (Homebridge info)
|
|
35
|
+
// Matter WARN → yellow (Homebridge warn)
|
|
36
|
+
// Matter ERROR/FATAL → red (Homebridge error)
|
|
37
|
+
let coloredMessage = messageText;
|
|
38
|
+
if (msg.level !== undefined) {
|
|
39
|
+
const levelStr = String(msg.level).toLowerCase();
|
|
40
|
+
if (levelStr === 'debug' || levelStr === 'info') {
|
|
41
|
+
// Homebridge debug style
|
|
42
|
+
coloredMessage = chalk.gray(messageText);
|
|
43
|
+
}
|
|
44
|
+
else if (levelStr === 'warn') {
|
|
45
|
+
// Homebridge warn style
|
|
46
|
+
coloredMessage = chalk.yellow(messageText);
|
|
47
|
+
}
|
|
48
|
+
else if (levelStr === 'error' || levelStr === 'fatal') {
|
|
49
|
+
// Homebridge error style
|
|
50
|
+
coloredMessage = chalk.red(messageText);
|
|
51
|
+
}
|
|
52
|
+
// For 'notice' or anything else, leave it uncolored (Homebridge info style)
|
|
53
|
+
}
|
|
54
|
+
// Check if timestamps are enabled (respects --no-timestamp flag)
|
|
55
|
+
if (timestampEnabled) {
|
|
56
|
+
// Format timestamp to match Homebridge format: [DD/MM/YYYY, HH:MM:SS AM/PM] in grey
|
|
57
|
+
const timestamp = formatHomebridgeTimestamp(msg.now);
|
|
58
|
+
return `${timestamp} ${facility} ${coloredMessage}`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// No timestamp
|
|
62
|
+
return `${facility} ${coloredMessage}`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Fallback for non-message diagnostics
|
|
67
|
+
return String(diagnostic);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format a date object to Homebridge timestamp format.
|
|
72
|
+
* Returns the timestamp in gray color.
|
|
73
|
+
*/
|
|
74
|
+
function formatHomebridgeTimestamp(date) {
|
|
75
|
+
const day = date.getDate().toString().padStart(2, '0');
|
|
76
|
+
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
77
|
+
const year = date.getFullYear();
|
|
78
|
+
// Convert to 12-hour format
|
|
79
|
+
let hours = date.getHours();
|
|
80
|
+
const ampm = hours >= 12 ? 'PM' : 'AM';
|
|
81
|
+
hours = hours % 12;
|
|
82
|
+
hours = hours || 12; // 0 should be 12
|
|
83
|
+
const hoursStr = hours.toString().padStart(2, '0');
|
|
84
|
+
const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
85
|
+
const seconds = date.getSeconds().toString().padStart(2, '0');
|
|
86
|
+
const timestamp = `[${day}/${month}/${year}, ${hoursStr}:${minutes}:${seconds} ${ampm}]`;
|
|
87
|
+
return formatGrey(timestamp);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Format text in gray color using chalk
|
|
91
|
+
*/
|
|
92
|
+
function formatGrey(text) {
|
|
93
|
+
return chalk.gray(text);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Format text in cyan color using chalk
|
|
97
|
+
*/
|
|
98
|
+
function formatCyan(text) {
|
|
99
|
+
return chalk.cyan(text);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Format the message values array into a readable string
|
|
103
|
+
*/
|
|
104
|
+
function formatMessageValues(values) {
|
|
105
|
+
if (!Array.isArray(values)) {
|
|
106
|
+
return String(values);
|
|
107
|
+
}
|
|
108
|
+
return values
|
|
109
|
+
.map((value) => {
|
|
110
|
+
if (value === null) {
|
|
111
|
+
return 'null';
|
|
112
|
+
}
|
|
113
|
+
if (value === undefined) {
|
|
114
|
+
return 'undefined';
|
|
115
|
+
}
|
|
116
|
+
if (typeof value === 'object') {
|
|
117
|
+
try {
|
|
118
|
+
return JSON.stringify(value);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return String(value);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return String(value);
|
|
125
|
+
})
|
|
126
|
+
.join(' ');
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=matterLogFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matterLogFormatter.js","sourceRoot":"","sources":["../../src/matter/matterLogFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC;;;;;GAKG;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,4BAA4B;IAC1C,2DAA2D;IAC3D,MAAM,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,EAAE,CAAA;IAEpD,OAAO,CAAC,UAAmB,EAAU,EAAE;QACrC,2CAA2C;QAC3C,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YAC1D,MAAM,GAAG,GAAG,UAAiB,CAAA;YAE7B,oDAAoD;YACpD,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC1C,yDAAyD;gBACzD,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAA;gBAEvD,uCAAuC;gBACvC,MAAM,WAAW,GAAG,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBAEnD,wCAAwC;gBACxC,8CAA8C;gBAC9C,6CAA6C;gBAC7C,yCAAyC;gBACzC,8CAA8C;gBAC9C,IAAI,cAAc,GAAG,WAAW,CAAA;gBAChC,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;oBAEhD,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;wBAChD,yBAAyB;wBACzB,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;oBAC1C,CAAC;yBAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;wBAC/B,wBAAwB;wBACxB,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;oBAC5C,CAAC;yBAAM,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;wBACxD,yBAAyB;wBACzB,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;oBACzC,CAAC;oBACD,4EAA4E;gBAC9E,CAAC;gBAED,iEAAiE;gBACjE,IAAI,gBAAgB,EAAE,CAAC;oBACrB,oFAAoF;oBACpF,MAAM,SAAS,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;oBACpD,OAAO,GAAG,SAAS,IAAI,QAAQ,IAAI,cAAc,EAAE,CAAA;gBACrD,CAAC;qBAAM,CAAC;oBACN,eAAe;oBACf,OAAO,GAAG,QAAQ,IAAI,cAAc,EAAE,CAAA;gBACxC,CAAC;YACH,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAA;IAC3B,CAAC,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAAC,IAAU;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAE/B,4BAA4B;IAC5B,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;IAC3B,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IACtC,KAAK,GAAG,KAAK,GAAG,EAAE,CAAA;IAClB,KAAK,GAAG,KAAK,IAAI,EAAE,CAAA,CAAC,iBAAiB;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAElD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAE7D,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,KAAK,IAAI,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,OAAO,IAAI,IAAI,GAAG,CAAA;IACxF,OAAO,UAAU,CAAC,SAAS,CAAC,CAAA;AAC9B,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,MAAiB;IAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;IACvB,CAAC;IAED,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,MAAM,CAAA;QACf,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,WAAW,CAAA;QACpB,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACtB,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC"}
|
|
@@ -8,7 +8,7 @@ import * as net from 'node:net';
|
|
|
8
8
|
import * as os from 'node:os';
|
|
9
9
|
import { Logger } from '../logger.js';
|
|
10
10
|
import { errorHandler, MatterErrorType } from './matterErrorHandler.js';
|
|
11
|
-
const log = Logger.withPrefix('Matter');
|
|
11
|
+
const log = Logger.withPrefix('Matter/Network');
|
|
12
12
|
export class MatterNetworkMonitor {
|
|
13
13
|
static instance;
|
|
14
14
|
status;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matterNetworkMonitor.js","sourceRoot":"","sources":["../../src/matter/matterNetworkMonitor.ts"],"names":[],"mappings":"AAAA,mBAAmB;AAEnB;;;;GAIG;AAEH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEvE,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"matterNetworkMonitor.js","sourceRoot":"","sources":["../../src/matter/matterNetworkMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -157,10 +157,6 @@ export declare class MatterServer extends EventEmitter {
|
|
|
157
157
|
* Get a specific accessory by UUID (Plugin API)
|
|
158
158
|
*/
|
|
159
159
|
getAccessory(uuid: string): MatterAccessory | undefined;
|
|
160
|
-
/**
|
|
161
|
-
* Configure a Matter endpoint after it's been added to the aggregator
|
|
162
|
-
*/
|
|
163
|
-
private configureEndpoint;
|
|
164
160
|
/**
|
|
165
161
|
* Stop the Matter server
|
|
166
162
|
*/
|
|
@@ -263,5 +259,11 @@ export declare class MatterServer extends EventEmitter {
|
|
|
263
259
|
* Check if a specific fabric exists
|
|
264
260
|
*/
|
|
265
261
|
hasFabric(fabricIndex: number): boolean;
|
|
262
|
+
/**
|
|
263
|
+
* Notify controllers that the parts list has changed
|
|
264
|
+
* This triggers controllers (like Home app) to re-read the device list
|
|
265
|
+
* and discover new or removed accessories without needing to re-pair
|
|
266
|
+
*/
|
|
267
|
+
private notifyPartsListChanged;
|
|
266
268
|
}
|
|
267
269
|
//# sourceMappingURL=matterServer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matterServer.d.ts","sourceRoot":"","sources":["../../src/matter/matterServer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"matterServer.d.ts","sourceRoot":"","sources":["../../src/matter/matterServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ import { access, writeFile } from 'node:fs/promises';
|
|
|
11
11
|
import * as os from 'node:os';
|
|
12
12
|
import * as path from 'node:path';
|
|
13
13
|
import process from 'node:process';
|
|
14
|
-
import { Endpoint, Environment, ServerNode, StorageService, VendorId } from '@matter/main';
|
|
14
|
+
import { Endpoint, Environment, Logger as MatterLogger, LogLevel as MatterLogLevel, ServerNode, StorageService, VendorId, } from '@matter/main';
|
|
15
15
|
import { AggregatorEndpoint } from '@matter/main/endpoints';
|
|
16
16
|
import { ManualPairingCodeCodec, QrPairingCodeCodec } from '@matter/types/schema';
|
|
17
17
|
import * as fse from 'fs-extra';
|
|
@@ -22,10 +22,11 @@ import { MatterAccessoryCache } from './matterAccessoryCache.js';
|
|
|
22
22
|
import { HomebridgeColorControlServer, HomebridgeDoorLockServer, HomebridgeIdentifyServer, HomebridgeLevelControlServer, HomebridgeOnOffServer, HomebridgeThermostatServer, HomebridgeWindowCoveringServer, registerHandler, setAccessoriesMap, } from './matterBehaviors.js';
|
|
23
23
|
import { sanitizeUniqueId, truncateString, validatePort } from './matterConfigValidator.js';
|
|
24
24
|
import { errorHandler } from './matterErrorHandler.js';
|
|
25
|
+
import { createHomebridgeLogFormatter } from './matterLogFormatter.js';
|
|
25
26
|
import { networkMonitor } from './matterNetworkMonitor.js';
|
|
26
27
|
import { MatterStorageManager } from './matterStorage.js';
|
|
27
28
|
import { clusters, deviceTypes, MatterDeviceError, } from './matterTypes.js';
|
|
28
|
-
const log = Logger.withPrefix('Matter');
|
|
29
|
+
const log = Logger.withPrefix('Matter/Server');
|
|
29
30
|
// Constants for Matter server configuration
|
|
30
31
|
const DEFAULT_MATTER_PORT = 5540;
|
|
31
32
|
const DEFAULT_VENDOR_ID = 0xFFF1; // Test vendor ID from Matter spec
|
|
@@ -68,10 +69,18 @@ export class MatterServer extends EventEmitter {
|
|
|
68
69
|
super();
|
|
69
70
|
// Store the validated config
|
|
70
71
|
this.config = this.validateAndSanitizeConfig(config);
|
|
71
|
-
//
|
|
72
|
+
// Configure Matter.js library logging
|
|
73
|
+
// Suppress DEBUG/INFO logs from Matter.js library unless debug mode is explicitly enabled
|
|
72
74
|
if (this.config.debugModeEnabled) {
|
|
73
75
|
log.info('Matter debug mode enabled - verbose logging active');
|
|
76
|
+
MatterLogger.level = MatterLogLevel.DEBUG;
|
|
74
77
|
}
|
|
78
|
+
else {
|
|
79
|
+
MatterLogger.level = MatterLogLevel.NOTICE;
|
|
80
|
+
}
|
|
81
|
+
// Set custom log format to match homebridge format:
|
|
82
|
+
// [DD/MM/YYYY, HH:MM:SS] [Matter/Facility] message
|
|
83
|
+
MatterLogger.format = createHomebridgeLogFormatter();
|
|
75
84
|
// Initialize commissioning values (will be loaded from storage in start())
|
|
76
85
|
this.vendorId = DEFAULT_VENDOR_ID;
|
|
77
86
|
this.productId = DEFAULT_PRODUCT_ID;
|
|
@@ -786,6 +795,73 @@ export class MatterServer extends EventEmitter {
|
|
|
786
795
|
// Modify device type with custom behaviors if handlers are defined
|
|
787
796
|
let deviceType = accessory.deviceType;
|
|
788
797
|
if (accessory.handlers) {
|
|
798
|
+
// IMPORTANT: Detect ColorControl features BEFORE modifying device type
|
|
799
|
+
// Once we start applying custom behaviors, the original structure is lost
|
|
800
|
+
let colorControlFeatures = null;
|
|
801
|
+
if (accessory.handlers.colorControl) {
|
|
802
|
+
const deviceTypeDef = deviceType;
|
|
803
|
+
const existingBehaviors = deviceTypeDef.behaviors;
|
|
804
|
+
if (existingBehaviors) {
|
|
805
|
+
// Behaviors can be an array, Set, or object - handle all cases
|
|
806
|
+
let behaviorsArray;
|
|
807
|
+
if (Array.isArray(existingBehaviors)) {
|
|
808
|
+
behaviorsArray = existingBehaviors;
|
|
809
|
+
}
|
|
810
|
+
else if (typeof existingBehaviors === 'object') {
|
|
811
|
+
// It's an object - get the values
|
|
812
|
+
behaviorsArray = Object.values(existingBehaviors);
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
// Try Array.from as fallback for Sets, Maps, etc.
|
|
816
|
+
behaviorsArray = Array.from(existingBehaviors);
|
|
817
|
+
}
|
|
818
|
+
for (const behavior of behaviorsArray) {
|
|
819
|
+
if (behavior.id === 'colorControl' || behavior.cluster?.id === 0x0300) {
|
|
820
|
+
if (behavior.cluster?.supportedFeatures) {
|
|
821
|
+
const features = behavior.cluster.supportedFeatures;
|
|
822
|
+
colorControlFeatures = [];
|
|
823
|
+
// supportedFeatures is an object with boolean properties, not a bitmap
|
|
824
|
+
if (features.hueSaturation) {
|
|
825
|
+
colorControlFeatures.push('HueSaturation');
|
|
826
|
+
}
|
|
827
|
+
if (features.xy) {
|
|
828
|
+
colorControlFeatures.push('Xy');
|
|
829
|
+
}
|
|
830
|
+
if (features.colorTemperature) {
|
|
831
|
+
colorControlFeatures.push('ColorTemperature');
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
// IMPORTANT: Adjust features based on provided handlers
|
|
835
|
+
// Add missing features and remove features without handlers
|
|
836
|
+
if (accessory.handlers.colorControl) {
|
|
837
|
+
if (!colorControlFeatures) {
|
|
838
|
+
colorControlFeatures = [];
|
|
839
|
+
}
|
|
840
|
+
const handlers = accessory.handlers.colorControl;
|
|
841
|
+
const finalFeatures = [];
|
|
842
|
+
// Check each possible feature and only include it if the handler is provided
|
|
843
|
+
// HueSaturation feature
|
|
844
|
+
if ('moveToHueAndSaturationLogic' in handlers) {
|
|
845
|
+
finalFeatures.push('HueSaturation');
|
|
846
|
+
}
|
|
847
|
+
// Xy feature
|
|
848
|
+
if ('moveToColorLogic' in handlers) {
|
|
849
|
+
finalFeatures.push('Xy');
|
|
850
|
+
}
|
|
851
|
+
// ColorTemperature feature
|
|
852
|
+
if ('moveToColorTemperatureLogic' in handlers) {
|
|
853
|
+
finalFeatures.push('ColorTemperature');
|
|
854
|
+
}
|
|
855
|
+
colorControlFeatures = finalFeatures;
|
|
856
|
+
}
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
else {
|
|
862
|
+
log.warn(`No behaviors found on device type for ${accessory.displayName}`);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
789
865
|
// Map cluster names to custom behavior classes
|
|
790
866
|
// Only clusters with user-triggered commands need custom behaviors
|
|
791
867
|
const behaviorMap = {
|
|
@@ -804,7 +880,12 @@ export class MatterServer extends EventEmitter {
|
|
|
804
880
|
// Build array of custom behaviors to apply based on what handlers are defined
|
|
805
881
|
const customBehaviors = [];
|
|
806
882
|
for (const clusterName of Object.keys(accessory.handlers)) {
|
|
807
|
-
|
|
883
|
+
let behaviorClass = behaviorMap[clusterName];
|
|
884
|
+
// Apply ColorControl features if we detected them earlier
|
|
885
|
+
if (clusterName === 'colorControl' && behaviorClass && colorControlFeatures && colorControlFeatures.length > 0) {
|
|
886
|
+
behaviorClass = behaviorClass.with(...colorControlFeatures);
|
|
887
|
+
log.info(`ColorControl custom behavior will preserve features: ${colorControlFeatures.join(', ')}`);
|
|
888
|
+
}
|
|
808
889
|
if (behaviorClass) {
|
|
809
890
|
customBehaviors.push(behaviorClass);
|
|
810
891
|
log.info(`Will use ${behaviorClass.name} for ${accessory.displayName}`);
|
|
@@ -819,17 +900,33 @@ export class MatterServer extends EventEmitter {
|
|
|
819
900
|
log.info(`Applied ${customBehaviors.length} custom behavior(s) to device type`);
|
|
820
901
|
}
|
|
821
902
|
}
|
|
822
|
-
// Create endpoint with the modified device type
|
|
823
|
-
|
|
903
|
+
// Create endpoint with the modified device type AND initial cluster states
|
|
904
|
+
// IMPORTANT: Cluster states must be provided at creation time, before adding to aggregator
|
|
905
|
+
// This ensures mandatory attributes are set before Matter.js validates the endpoint
|
|
906
|
+
const endpointOptions = {
|
|
824
907
|
id: accessory.uuid,
|
|
825
|
-
|
|
826
|
-
|
|
908
|
+
...accessory.clusters, // Spread cluster states as initial values
|
|
909
|
+
};
|
|
910
|
+
const endpoint = new Endpoint(deviceType, endpointOptions);
|
|
911
|
+
if (this.config.debugModeEnabled) {
|
|
912
|
+
log.debug(`Created endpoint for ${accessory.displayName} with initial cluster states`);
|
|
913
|
+
}
|
|
914
|
+
// Add to aggregator (validation happens here - cluster states must already be set)
|
|
827
915
|
await this.aggregator.add(endpoint);
|
|
828
916
|
if (this.config.debugModeEnabled) {
|
|
829
917
|
log.debug(`Added endpoint for ${accessory.displayName} to aggregator`);
|
|
830
918
|
}
|
|
831
|
-
//
|
|
832
|
-
|
|
919
|
+
// Set up command handlers if provided
|
|
920
|
+
if (accessory.handlers) {
|
|
921
|
+
log.info(`Setting up handlers for accessory ${accessory.uuid}`);
|
|
922
|
+
// Register handlers with the custom behavior classes
|
|
923
|
+
for (const [clusterName, handlers] of Object.entries(accessory.handlers)) {
|
|
924
|
+
log.info(` Processing cluster: ${clusterName}`);
|
|
925
|
+
for (const [commandName, handler] of Object.entries(handlers)) {
|
|
926
|
+
registerHandler(accessory.uuid, clusterName, commandName, handler);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
833
930
|
// Store accessory
|
|
834
931
|
const internalAccessory = {
|
|
835
932
|
...accessory,
|
|
@@ -843,6 +940,9 @@ export class MatterServer extends EventEmitter {
|
|
|
843
940
|
}
|
|
844
941
|
// Emit accessory-registered event
|
|
845
942
|
this.emit('accessory-registered', accessory);
|
|
943
|
+
// Notify controllers about the new device (parts list changed)
|
|
944
|
+
// This allows the Home app to discover new devices without re-pairing
|
|
945
|
+
await this.notifyPartsListChanged();
|
|
846
946
|
// Save to cache asynchronously (don't block registration)
|
|
847
947
|
if (this.accessoryCache) {
|
|
848
948
|
this.accessoryCache.save(this.accessories).catch((error) => {
|
|
@@ -873,6 +973,8 @@ export class MatterServer extends EventEmitter {
|
|
|
873
973
|
log.info(`Unregistered Matter accessory: ${accessory.displayName} (${uuid})`);
|
|
874
974
|
// Emit accessory-unregistered event
|
|
875
975
|
this.emit('accessory-unregistered', uuid);
|
|
976
|
+
// Notify controllers about the removed device (parts list changed)
|
|
977
|
+
await this.notifyPartsListChanged();
|
|
876
978
|
// Update cache (remove the accessory)
|
|
877
979
|
if (this.accessoryCache) {
|
|
878
980
|
this.accessoryCache.removeCached(uuid);
|
|
@@ -1021,48 +1123,6 @@ export class MatterServer extends EventEmitter {
|
|
|
1021
1123
|
const { endpoint, registered, ...publicAccessory } = accessory;
|
|
1022
1124
|
return publicAccessory;
|
|
1023
1125
|
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Configure a Matter endpoint after it's been added to the aggregator
|
|
1026
|
-
*/
|
|
1027
|
-
async configureEndpoint(endpoint, accessory) {
|
|
1028
|
-
// Note: bridgedDeviceBasicInformation is not available in Matter.js v0.15.4
|
|
1029
|
-
// The BridgedDeviceBasicInformation cluster is automatically added to bridged devices
|
|
1030
|
-
// but cannot be configured via endpoint.set() in this version
|
|
1031
|
-
// Leaving this commented out to avoid error logs
|
|
1032
|
-
// try {
|
|
1033
|
-
// await endpoint.set({
|
|
1034
|
-
// bridgedDeviceBasicInformation: {
|
|
1035
|
-
// nodeLabel: accessory.displayName.slice(0, 32),
|
|
1036
|
-
// vendorName: accessory.manufacturer.slice(0, 32),
|
|
1037
|
-
// vendorId: VendorId(this.vendorId),
|
|
1038
|
-
// productName: accessory.model.slice(0, 32),
|
|
1039
|
-
// productLabel: accessory.displayName.slice(0, 64),
|
|
1040
|
-
// serialNumber: accessory.serialNumber,
|
|
1041
|
-
// reachable: true,
|
|
1042
|
-
// ...(accessory.hardwareRevision && { hardwareVersionString: accessory.hardwareRevision }),
|
|
1043
|
-
// ...(accessory.softwareVersion && { softwareVersionString: accessory.softwareVersion }),
|
|
1044
|
-
// },
|
|
1045
|
-
// } as any)
|
|
1046
|
-
// } catch (error) {
|
|
1047
|
-
// log.debug(`Could not set bridgedDeviceBasicInformation for ${accessory.displayName}: ${error}`)
|
|
1048
|
-
// }
|
|
1049
|
-
// Set up cluster states
|
|
1050
|
-
for (const [clusterName, attributes] of Object.entries(accessory.clusters)) {
|
|
1051
|
-
// Cast to any temporarily to work around Matter.js type limitations
|
|
1052
|
-
await endpoint.set({ [clusterName]: attributes });
|
|
1053
|
-
}
|
|
1054
|
-
// Set up command handlers if provided
|
|
1055
|
-
if (accessory.handlers) {
|
|
1056
|
-
log.info(`Setting up handlers for accessory ${accessory.uuid}`);
|
|
1057
|
-
// Register handlers with the custom behavior classes
|
|
1058
|
-
for (const [clusterName, handlers] of Object.entries(accessory.handlers)) {
|
|
1059
|
-
log.info(` Processing cluster: ${clusterName}`);
|
|
1060
|
-
for (const [commandName, handler] of Object.entries(handlers)) {
|
|
1061
|
-
registerHandler(accessory.uuid, clusterName, commandName, handler);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
1126
|
/**
|
|
1067
1127
|
* Stop the Matter server
|
|
1068
1128
|
*/
|
|
@@ -1262,5 +1322,41 @@ export class MatterServer extends EventEmitter {
|
|
|
1262
1322
|
const fabrics = this.getFabricInfo();
|
|
1263
1323
|
return fabrics.some(f => f.fabricIndex === fabricIndex);
|
|
1264
1324
|
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Notify controllers that the parts list has changed
|
|
1327
|
+
* This triggers controllers (like Home app) to re-read the device list
|
|
1328
|
+
* and discover new or removed accessories without needing to re-pair
|
|
1329
|
+
*/
|
|
1330
|
+
async notifyPartsListChanged() {
|
|
1331
|
+
if (!this.aggregator || !this.isCommissioned()) {
|
|
1332
|
+
// No controllers connected, skip notification
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
try {
|
|
1336
|
+
// Access the aggregator's descriptor cluster state
|
|
1337
|
+
// The partsList is automatically updated by Matter.js when endpoints are added/removed
|
|
1338
|
+
// We just need to ensure controllers are notified of the change
|
|
1339
|
+
const aggregatorState = this.aggregator;
|
|
1340
|
+
if (aggregatorState.state?.descriptor) {
|
|
1341
|
+
// Get current parts list (endpoint numbers of all children)
|
|
1342
|
+
const partsList = aggregatorState.state.descriptor.partsList || [];
|
|
1343
|
+
if (this.config.debugModeEnabled) {
|
|
1344
|
+
log.debug(`Parts list changed: ${partsList.length} devices (endpoints: ${partsList.join(', ')})`);
|
|
1345
|
+
}
|
|
1346
|
+
// Trigger a state update event to notify subscribed controllers
|
|
1347
|
+
// By setting the partsList to itself, we trigger the change notification
|
|
1348
|
+
await this.aggregator.set({
|
|
1349
|
+
descriptor: {
|
|
1350
|
+
partsList,
|
|
1351
|
+
},
|
|
1352
|
+
});
|
|
1353
|
+
log.info(`Notified controllers of parts list change (${this.accessories.size} devices)`);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
catch (error) {
|
|
1357
|
+
// Non-fatal error - log but don't throw
|
|
1358
|
+
log.warn(`Failed to notify controllers of parts list change: ${error.message}`);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1265
1361
|
}
|
|
1266
1362
|
//# sourceMappingURL=matterServer.js.map
|