matterbridge 1.1.4 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +12 -9
- package/dist/AirQualityCluster.d.ts.map +1 -1
- package/dist/AirQualityCluster.js +1 -7
- package/dist/AirQualityCluster.js.map +1 -1
- package/dist/TvocCluster.d.ts.map +1 -1
- package/dist/TvocCluster.js +1 -2
- package/dist/TvocCluster.js.map +1 -1
- package/dist/matterbridge.d.ts +14 -5
- package/dist/matterbridge.d.ts.map +1 -1
- package/dist/matterbridge.js +408 -236
- package/dist/matterbridge.js.map +1 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +7 -13
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -1
- package/dist/matterbridgeAccessoryPlatform.js +9 -18
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -1
- package/dist/matterbridgeController.d.ts +23 -1
- package/dist/matterbridgeController.d.ts.map +1 -1
- package/dist/matterbridgeController.js +364 -293
- package/dist/matterbridgeController.js.map +1 -1
- package/dist/matterbridgeDevice.d.ts +16 -0
- package/dist/matterbridgeDevice.d.ts.map +1 -1
- package/dist/matterbridgeDevice.js +34 -13
- package/dist/matterbridgeDevice.js.map +1 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +7 -13
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -1
- package/dist/matterbridgeDynamicPlatform.js +9 -18
- package/dist/matterbridgeDynamicPlatform.js.map +1 -1
- package/frontend/build/asset-manifest.json +3 -3
- package/frontend/build/index.html +1 -1
- package/frontend/build/manifest.json +2 -2
- package/frontend/build/matterbridge 32x32.png +0 -0
- package/frontend/build/matterbridge 64x64.png +0 -0
- package/frontend/build/static/js/{main.b5a876cf.js → main.e5888ebb.js} +3 -3
- package/frontend/build/static/js/main.e5888ebb.js.map +1 -0
- package/package.json +71 -69
- package/frontend/build/static/js/main.b5a876cf.js.map +0 -1
- /package/frontend/build/static/js/{main.b5a876cf.js.LICENSE.txt → main.e5888ebb.js.LICENSE.txt} +0 -0
|
@@ -1,309 +1,380 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* This file contains the class MatterbridgeController.
|
|
3
|
+
*
|
|
4
|
+
* @file matterbridge.ts
|
|
5
|
+
* @author Luca Liguori
|
|
6
|
+
* @date 2023-12-29
|
|
7
|
+
* @version 1.2.0
|
|
8
|
+
*
|
|
9
|
+
* Copyright 2023, 2024 Luca Liguori.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License. *
|
|
22
|
+
*/
|
|
23
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
24
|
+
/* eslint-disable no-console */
|
|
2
25
|
/* eslint-disable max-len */
|
|
3
26
|
/*
|
|
4
|
-
|
|
5
|
-
log.info('Creating mattercontrollerContext: mattercontrollerContext');
|
|
6
|
-
mattercontrollerContext = storageManager.createContext('mattercontrollerContext');
|
|
27
|
+
import { MatterbridgeDevice, SerializedMatterbridgeDevice } from './matterbridgeDevice.js';
|
|
7
28
|
|
|
8
|
-
|
|
29
|
+
import { NodeStorageManager, NodeStorage } from 'node-persist-manager';
|
|
30
|
+
import { AnsiLogger, BRIGHT, RESET, TimestampFormat, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, stringify, er, nf, rs, wr } from 'node-ansi-logger';
|
|
31
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
32
|
+
import { promises as fs } from 'fs';
|
|
33
|
+
import express from 'express';
|
|
34
|
+
import os from 'os';
|
|
35
|
+
import path from 'path';
|
|
9
36
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
console.log('ActiveSessionInformation:', commissioningController.getActiveSessionInformation());
|
|
65
|
-
} // (hasParameter('pairingcode'))
|
|
66
|
-
|
|
67
|
-
if (hasParameter('discover')) {
|
|
68
|
-
Logger.defaultLogLevel = Level.DEBUG;
|
|
69
|
-
const discover = await commissioningController.discoverCommissionableDevices({});
|
|
70
|
-
console.log(discover);
|
|
71
|
-
Logger.defaultLogLevel = Level.INFO;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
log.info(`Commissioning controller is already commisioned: ${commissioningController.isCommissioned()}`);
|
|
75
|
-
const nodes = commissioningController.getCommissionedNodes();
|
|
76
|
-
nodes.forEach(async (nodeId) => {
|
|
77
|
-
log.warn(`Connecting to commissioned node: ${nodeId}`);
|
|
78
|
-
const node = await commissioningController.connectNode(nodeId, {
|
|
79
|
-
attributeChangedCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, attributeName }, value }) =>
|
|
80
|
-
console.log(`\x1b[37;44mattributeChangedCallback ${peerNodeId}: Attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(value)}\x1b[40;0m`),
|
|
81
|
-
eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) =>
|
|
82
|
-
console.log(`\x1b[37;44meventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(events)}\x1b[40;0m`),
|
|
83
|
-
stateInformationCallback: (peerNodeId, info) => {
|
|
84
|
-
switch (info) {
|
|
85
|
-
case NodeStateInformation.Connected:
|
|
86
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} connected\x1b[40;0m`);
|
|
87
|
-
break;
|
|
88
|
-
case NodeStateInformation.Disconnected:
|
|
89
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected\x1b[40;0m`);
|
|
90
|
-
break;
|
|
91
|
-
case NodeStateInformation.Reconnecting:
|
|
92
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting\x1b[40;0m`);
|
|
93
|
-
break;
|
|
94
|
-
case NodeStateInformation.WaitingForDeviceDiscovery:
|
|
95
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery\x1b[40;0m`);
|
|
96
|
-
break;
|
|
97
|
-
case NodeStateInformation.StructureChanged:
|
|
98
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed\x1b[40;0m`);
|
|
99
|
-
break;
|
|
100
|
-
case NodeStateInformation.Decommissioned:
|
|
101
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned\x1b[40;0m`);
|
|
102
|
-
break;
|
|
103
|
-
default:
|
|
104
|
-
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} NodeStateInformation.${info}\x1b[40;0m`);
|
|
105
|
-
break;
|
|
37
|
+
import { CommissioningController, CommissioningServer, MatterServer } from '@project-chip/matter-node.js';
|
|
38
|
+
import { BasicInformationCluster, BridgedDeviceBasicInformationCluster, ClusterServer } from '@project-chip/matter-node.js/cluster';
|
|
39
|
+
import { DeviceTypeId, EndpointNumber, VendorId } from '@project-chip/matter-node.js/datatype';
|
|
40
|
+
import { Aggregator, Device, DeviceTypes } from '@project-chip/matter-node.js/device';
|
|
41
|
+
import { Format, Level, Logger } from '@project-chip/matter-node.js/log';
|
|
42
|
+
import { QrCodeSchema } from '@project-chip/matter-node.js/schema';
|
|
43
|
+
import { StorageBackendDisk, StorageBackendJsonFile, StorageContext, StorageManager } from '@project-chip/matter-node.js/storage';
|
|
44
|
+
import { requireMinNodeVersion, getParameter, getIntParameter, hasParameter } from '@project-chip/matter-node.js/util';
|
|
45
|
+
import { CryptoNode } from '@project-chip/matter-node.js/crypto';
|
|
46
|
+
import { logEndpoint } from '@project-chip/matter-node.js/device';
|
|
47
|
+
import { Matterbridge } from './matterbridge.js';
|
|
48
|
+
*/
|
|
49
|
+
export function startController() {
|
|
50
|
+
//const log: AnsiLogger;
|
|
51
|
+
/*
|
|
52
|
+
async startController() {
|
|
53
|
+
this.log.info('Creating mattercontrollerContext: mattercontrollerContext');
|
|
54
|
+
mattercontrollerContext = storageManager.createContext('mattercontrollerContext');
|
|
55
|
+
|
|
56
|
+
await createMatterServer(storageManager);
|
|
57
|
+
|
|
58
|
+
this.log.info('Creating matter commissioning controller');
|
|
59
|
+
commissioningController = new CommissioningController({
|
|
60
|
+
autoConnect: false,
|
|
61
|
+
});
|
|
62
|
+
await matterServer.addCommissioningController(commissioningController);
|
|
63
|
+
|
|
64
|
+
this.log.info('Starting matter server');
|
|
65
|
+
await matterServer.start();
|
|
66
|
+
this.log.info('Started matter server');
|
|
67
|
+
|
|
68
|
+
AllClustersMap[EveHistoryCluster.id] = EveHistoryCluster;
|
|
69
|
+
this.log.info('Added custom cluster:', getClusterNameById(EveHistoryCluster.id));
|
|
70
|
+
|
|
71
|
+
if (hasParameter('ble')) {
|
|
72
|
+
//
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (hasParameter('pairingcode')) {
|
|
76
|
+
const pairingCode = getParameter('pairingcode');
|
|
77
|
+
const ip = mattercontrollerContext.has('ip') ? mattercontrollerContext.get<string>('ip') : undefined;
|
|
78
|
+
const port = mattercontrollerContext.has('port') ? mattercontrollerContext.get<number>('port') : undefined;
|
|
79
|
+
|
|
80
|
+
let longDiscriminator, setupPin, shortDiscriminator;
|
|
81
|
+
if (pairingCode !== undefined) {
|
|
82
|
+
const pairingCodeCodec = ManualPairingCodeCodec.decode(pairingCode);
|
|
83
|
+
shortDiscriminator = pairingCodeCodec.shortDiscriminator;
|
|
84
|
+
longDiscriminator = undefined;
|
|
85
|
+
setupPin = pairingCodeCodec.passcode;
|
|
86
|
+
logger.debug(`Data extracted from pairing code: ${Logger.toJSON(pairingCodeCodec)}`);
|
|
87
|
+
} else {
|
|
88
|
+
longDiscriminator = mattercontrollerContext.get('longDiscriminator', 3840);
|
|
89
|
+
if (longDiscriminator > 4095) throw new Error('Discriminator value must be less than 4096');
|
|
90
|
+
setupPin = mattercontrollerContext.get('pin', 20202021);
|
|
106
91
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const eveHistory = device.getClusterClient(EveHistoryCluster);
|
|
173
|
-
if (eveHistory !== undefined) {
|
|
174
|
-
log.info(`EveHistory found on id: ${device.id} name: ${device.name}`);
|
|
175
|
-
|
|
176
|
-
// Log EveHistoryCluster
|
|
177
|
-
const attributesEveHistoryCluster = await interactionClient.getMultipleAttributes({
|
|
178
|
-
attributes: [{ clusterId: EveHistoryCluster.id }],
|
|
92
|
+
if ((shortDiscriminator === undefined && longDiscriminator === undefined) || setupPin === undefined) {
|
|
93
|
+
throw new Error('Please specify the longDiscriminator of the device to commission with -longDiscriminator or provide a valid passcode with -passcode');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const commissioningOptions: CommissioningOptions = {
|
|
97
|
+
regulatoryLocation: GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor,
|
|
98
|
+
regulatoryCountryCode: 'XX',
|
|
99
|
+
};
|
|
100
|
+
const options = {
|
|
101
|
+
commissioning: commissioningOptions,
|
|
102
|
+
discovery: {
|
|
103
|
+
knownAddress: ip !== undefined && port !== undefined ? { ip, port, type: 'udp' } : undefined,
|
|
104
|
+
identifierData: longDiscriminator !== undefined ? { longDiscriminator } : shortDiscriminator !== undefined ? { shortDiscriminator } : {},
|
|
105
|
+
},
|
|
106
|
+
passcode: setupPin,
|
|
107
|
+
} as NodeCommissioningOptions;
|
|
108
|
+
this.log.info(`Commissioning ... ${JSON.stringify(options)}`);
|
|
109
|
+
const nodeId = await commissioningController.commissionNode(options);
|
|
110
|
+
mattercontrollerContext.set('nodeId', nodeId.nodeId);
|
|
111
|
+
this.log.info(`Commissioning successfully done with nodeId: ${nodeId.nodeId}`);
|
|
112
|
+
console.log('ActiveSessionInformation:', commissioningController.getActiveSessionInformation());
|
|
113
|
+
} // (hasParameter('pairingcode'))
|
|
114
|
+
|
|
115
|
+
if (hasParameter('discover')) {
|
|
116
|
+
Logger.defaultLogLevel = Level.DEBUG;
|
|
117
|
+
const discover = await commissioningController.discoverCommissionableDevices({});
|
|
118
|
+
console.log(discover);
|
|
119
|
+
Logger.defaultLogLevel = Level.INFO;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.log.info(`Commissioning controller is already commisioned: ${commissioningController.isCommissioned()}`);
|
|
123
|
+
const nodes = commissioningController.getCommissionedNodes();
|
|
124
|
+
nodes.forEach(async (nodeId) => {
|
|
125
|
+
this.log.warn(`Connecting to commissioned node: ${nodeId}`);
|
|
126
|
+
const node = await commissioningController.connectNode(nodeId, {
|
|
127
|
+
attributeChangedCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, attributeName }, value }) =>
|
|
128
|
+
console.log(`\x1b[37;44mattributeChangedCallback ${peerNodeId}: Attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(value)}\x1b[40;0m`),
|
|
129
|
+
eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) =>
|
|
130
|
+
console.log(`\x1b[37;44meventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(events)}\x1b[40;0m`),
|
|
131
|
+
stateInformationCallback: (peerNodeId, info) => {
|
|
132
|
+
switch (info) {
|
|
133
|
+
case NodeStateInformation.Connected:
|
|
134
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} connected\x1b[40;0m`);
|
|
135
|
+
break;
|
|
136
|
+
case NodeStateInformation.Disconnected:
|
|
137
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected\x1b[40;0m`);
|
|
138
|
+
break;
|
|
139
|
+
case NodeStateInformation.Reconnecting:
|
|
140
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting\x1b[40;0m`);
|
|
141
|
+
break;
|
|
142
|
+
case NodeStateInformation.WaitingForDeviceDiscovery:
|
|
143
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery\x1b[40;0m`);
|
|
144
|
+
break;
|
|
145
|
+
case NodeStateInformation.StructureChanged:
|
|
146
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed\x1b[40;0m`);
|
|
147
|
+
break;
|
|
148
|
+
case NodeStateInformation.Decommissioned:
|
|
149
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned\x1b[40;0m`);
|
|
150
|
+
break;
|
|
151
|
+
default:
|
|
152
|
+
console.log(`\x1b[37;44mstateInformationCallback ${peerNodeId}: Node ${nodeId} NodeStateInformation.${info}\x1b[40;0m`);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
179
156
|
});
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
157
|
+
|
|
158
|
+
const info = node.getRootClusterClient(BasicInformationCluster);
|
|
159
|
+
let name = '';
|
|
160
|
+
if (info !== undefined) {
|
|
161
|
+
this.log.info(`Node ${nodeId} VendorName ${await info.getVendorNameAttribute()}`); // This call is executed remotely
|
|
162
|
+
this.log.info(`Node ${nodeId} ProductName ${(name = await info.getProductNameAttribute())}`); // This call is executed remotely
|
|
163
|
+
this.log.info(`Node ${nodeId} NodeLabel ${await info.getNodeLabelAttribute()}`); // This call is executed remotely
|
|
164
|
+
this.log.info(`Node ${nodeId} ProductLabel ${await info.getProductLabelAttribute()}`); // This call is executed remotely
|
|
165
|
+
this.log.info(`Node ${nodeId} SerialNumber ${await info.getSerialNumberAttribute()}`); // This call is executed remotely
|
|
166
|
+
this.log.info(`Node ${nodeId} UniqueId ${await info.getUniqueIdAttribute()}`); // This call is executed remotely
|
|
167
|
+
} else {
|
|
168
|
+
this.log.error('No BasicInformation Cluster found. This should never happen!');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this.log.warn(`Logging commissioned node: ${nodeId} name: ${name}`);
|
|
172
|
+
//node.logStructure();
|
|
173
|
+
|
|
174
|
+
const mattercontrollerNodeContext = storageManager.createContext(name);
|
|
175
|
+
const interactionClient = await node.getInteractionClient();
|
|
176
|
+
|
|
177
|
+
// Log BasicInformationCluster
|
|
178
|
+
const attributesInfoCluster = await interactionClient.getMultipleAttributes({
|
|
179
|
+
attributes: [{ clusterId: BasicInformationCluster.id }],
|
|
180
|
+
});
|
|
181
|
+
attributesInfoCluster.forEach((attribute) => {
|
|
182
|
+
this.log.info(
|
|
183
|
+
`${name}:BasicInformationCluster ${attribute.path.nodeId}-${attribute.path.endpointId}-${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
|
|
183
184
|
);
|
|
184
185
|
});
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
eveHistory.subscribeHistoryStatusAttribute(
|
|
228
|
-
(value: Uint8Array) => { log.warn('Received EveHistoryStatus:', value.toHex()) }, 0, 30)
|
|
229
|
-
.then(() => { log.warn('Subscription successful to EveHistoryStatus.') })
|
|
230
|
-
.catch((error) => { log.error('Error during subscription to EveHistoryStatus:', error) });
|
|
231
|
-
|
|
232
|
-
eveHistory.subscribeHistoryEntriesAttribute(
|
|
233
|
-
(value: Uint8Array) => { log.warn('Received EveHistoryEntries:', value.toHex()) }, 0, 30)
|
|
234
|
-
.then(() => { log.warn('Subscription successful to EveHistoryEntries.') })
|
|
235
|
-
.catch((error) => { log.error('Error during subscription to EveHistoryEntries:', error) });
|
|
236
|
-
|
|
237
|
-
setInterval(async () => {
|
|
238
|
-
try {
|
|
239
|
-
const attributesEveCluster = await interactionClient.getMultipleAttributes({
|
|
186
|
+
|
|
187
|
+
// Log PowerSourceConfigurationCluster
|
|
188
|
+
const attributesPowerConfigCluster = await interactionClient.getMultipleAttributes({
|
|
189
|
+
attributes: [{ clusterId: PowerSourceConfigurationCluster.id }],
|
|
190
|
+
});
|
|
191
|
+
attributesPowerConfigCluster.forEach((attribute) => {
|
|
192
|
+
this.log.info(
|
|
193
|
+
`${name}:PowerSourceConfigurationCluster ${attribute.path.nodeId}-${attribute.path.endpointId}-${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Log PowerSourceCluster
|
|
198
|
+
const attributesPowerCluster = await interactionClient.getMultipleAttributes({
|
|
199
|
+
attributes: [{ clusterId: PowerSourceCluster.id }],
|
|
200
|
+
});
|
|
201
|
+
attributesPowerCluster.forEach((attribute) => {
|
|
202
|
+
this.log.info(
|
|
203
|
+
`${name}:PowerSourceCluster ${attribute.path.nodeId}-${attribute.path.endpointId}-${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
|
|
204
|
+
);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Log ThreadNetworkDiagnostics
|
|
208
|
+
const attributesThreadCluster = await interactionClient.getMultipleAttributes({
|
|
209
|
+
attributes: [{ clusterId: ThreadNetworkDiagnosticsCluster.id }],
|
|
210
|
+
});
|
|
211
|
+
attributesThreadCluster.forEach((attribute) => {
|
|
212
|
+
this.log.info(
|
|
213
|
+
`${name}:ThreadNetworkDiagnosticsCluster ${attribute.path.nodeId}-${attribute.path.endpointId}-${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const devices = node.getDevices();
|
|
218
|
+
devices.forEach(async (device) => {
|
|
219
|
+
this.log.info(`Device id: ${device.id} name: ${device.name}`);
|
|
220
|
+
//logEndpoint(device);
|
|
221
|
+
|
|
222
|
+
const eveHistory = device.getClusterClient(EveHistoryCluster);
|
|
223
|
+
if (eveHistory !== undefined) {
|
|
224
|
+
this.log.info(`EveHistory found on id: ${device.id} name: ${device.name}`);
|
|
225
|
+
|
|
226
|
+
// Log EveHistoryCluster
|
|
227
|
+
const attributesEveHistoryCluster = await interactionClient.getMultipleAttributes({
|
|
240
228
|
attributes: [{ clusterId: EveHistoryCluster.id }],
|
|
241
229
|
});
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
230
|
+
attributesEveHistoryCluster.forEach((attribute) => {
|
|
231
|
+
this.log.info(
|
|
232
|
+
`${name}:EveHistoryCluster ${attribute.path.nodeId}-${attribute.path.endpointId}-${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
|
|
233
|
+
);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const history = new MatterHistory(this.log, name, { fileName: name + '_history.json' });
|
|
237
|
+
let logMessage = '';
|
|
238
|
+
|
|
239
|
+
// Get and decode HistoryStatus
|
|
240
|
+
const historyStatus: Uint8Array = await eveHistory.getHistoryStatusAttribute();
|
|
241
|
+
this.log.info((logMessage = history.decodeHistoryStatus(Buffer.from(historyStatus))));
|
|
242
|
+
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
243
|
+
|
|
244
|
+
// Set HistorySetTime
|
|
245
|
+
const bufferSetTime = history.encodeHistorySetTime();
|
|
246
|
+
this.log.info((logMessage = history.decodeHistorySetTime(bufferSetTime)));
|
|
247
|
+
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
248
|
+
await eveHistory.setHistorySetTimeAttribute(bufferSetTime);
|
|
249
|
+
|
|
250
|
+
// Set HistoryRequest
|
|
251
|
+
const entryNumber = mattercontrollerNodeContext.get('nextEntry', history.getFirstEntry());
|
|
252
|
+
const bufferRequest = history.encodeHistoryRequest(history.clamp(entryNumber, history.getFirstEntry(), history.getLastEntry()));
|
|
253
|
+
this.log.info((logMessage = history.decodeHistoryRequest(bufferRequest)));
|
|
254
|
+
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
255
|
+
await eveHistory.setHistoryRequestAttribute(bufferRequest);
|
|
256
|
+
|
|
257
|
+
// Get HistoryEntries
|
|
258
|
+
let historyEntries: Uint8Array = await eveHistory.getHistoryEntriesAttribute();
|
|
259
|
+
let bufferHistoryEntries = Buffer.from(historyEntries);
|
|
260
|
+
//console.log(history.historyEntriesToString(bufferHistoryEntries));
|
|
261
|
+
while (bufferHistoryEntries.length > 0) {
|
|
262
|
+
for (let i = 0; i < bufferHistoryEntries.length; ) {
|
|
263
|
+
const bufferHistoryEntry = Buffer.copyBytesFrom(bufferHistoryEntries, i, bufferHistoryEntries.readUInt8(i));
|
|
264
|
+
i += bufferHistoryEntries.readUInt8(i);
|
|
265
|
+
history.decodeHistoryEntry(bufferHistoryEntry);
|
|
266
|
+
this.log.info((logMessage = history.historyEntryToString(bufferHistoryEntry)));
|
|
254
267
|
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
255
|
-
|
|
256
|
-
const bufferHistoryEntries = Buffer.from(attribute.value);
|
|
257
|
-
for (let i = 0; i < bufferHistoryEntries.length; ) {
|
|
258
|
-
const bufferHistoryEntry = Buffer.copyBytesFrom(bufferHistoryEntries, i, bufferHistoryEntries.readUInt8(i));
|
|
259
|
-
i += bufferHistoryEntries.readUInt8(i);
|
|
260
|
-
history.decodeHistoryEntry(bufferHistoryEntry);
|
|
261
|
-
log.info((logMessage = history.historyEntryToString(bufferHistoryEntry)));
|
|
262
|
-
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
263
|
-
}
|
|
264
|
-
history.writeHistoryFile();
|
|
265
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.TimesOpened.id) {
|
|
266
|
-
log.info(`TimesOpened: ${attribute.value}`);
|
|
267
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.LastEvent.id) {
|
|
268
|
-
log.info(`LastEvent: ${attribute.value}=${history.secsToDateString(attribute.value + history.getInitialTime() - history.getTimeOffset())}`);
|
|
269
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.ResetTotal.id) {
|
|
270
|
-
log.info(`ResetTotal: ${attribute.value}=${history.secsToDateStringSinceEveEpoch(attribute.value)}`);
|
|
271
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.Voltage.id) {
|
|
272
|
-
log.info(`Voltage: ${attribute.value}`);
|
|
273
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.Current.id) {
|
|
274
|
-
log.info(`Current: ${attribute.value}`);
|
|
275
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.Consumption.id) {
|
|
276
|
-
log.info(`Consumption: ${attribute.value}`);
|
|
277
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.TotalConsumption.id) {
|
|
278
|
-
log.info(`TotalConsumption: ${attribute.value}`);
|
|
279
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.ChildLock.id) {
|
|
280
|
-
log.info(`ChildLock: ${attribute.value}`);
|
|
281
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.MotionSensitivity.id) {
|
|
282
|
-
log.info(`MotionSensitivity: ${attribute.value}`);
|
|
283
|
-
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.RLoc.id) {
|
|
284
|
-
log.info((logMessage = `RLoc: 0x${attribute.value.toString(16)}`));
|
|
285
|
-
} else {
|
|
286
|
-
if (attribute.path.attributeId >= 0x130a0000) {
|
|
287
|
-
log.info(`Unknown attribute ${attribute.path.attributeName} type: ${typeof attribute.value} value: [${attribute.value.toString(16)}]${attribute.value}`);
|
|
288
|
-
}
|
|
268
|
+
mattercontrollerNodeContext.set('nextEntry', bufferHistoryEntry.readUInt32LE(1) + 1);
|
|
289
269
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
270
|
+
historyEntries = await eveHistory.getHistoryEntriesAttribute();
|
|
271
|
+
bufferHistoryEntries = Buffer.from(historyEntries);
|
|
272
|
+
//console.log(history.historyEntriesToString(bufferHistoryEntries));
|
|
273
|
+
}
|
|
274
|
+
history.writeHistoryFile();
|
|
275
|
+
//history.logHistory(true);
|
|
276
|
+
|
|
277
|
+
eveHistory
|
|
278
|
+
.subscribeHistoryStatusAttribute(
|
|
279
|
+
(value: Uint8Array) => {
|
|
280
|
+
this.log.warn('Received EveHistoryStatus:', value.toHex());
|
|
281
|
+
},
|
|
282
|
+
0,
|
|
283
|
+
30,
|
|
284
|
+
)
|
|
285
|
+
.then(() => {
|
|
286
|
+
this.log.warn('Subscription successful to EveHistoryStatus.');
|
|
287
|
+
})
|
|
288
|
+
.catch((error) => {
|
|
289
|
+
this.log.error('Error during subscription to EveHistoryStatus:', error);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
eveHistory
|
|
293
|
+
.subscribeHistoryEntriesAttribute(
|
|
294
|
+
(value: Uint8Array) => {
|
|
295
|
+
this.log.warn('Received EveHistoryEntries:', value.toHex());
|
|
296
|
+
},
|
|
297
|
+
0,
|
|
298
|
+
30,
|
|
299
|
+
)
|
|
300
|
+
.then(() => {
|
|
301
|
+
this.log.warn('Subscription successful to EveHistoryEntries.');
|
|
302
|
+
})
|
|
303
|
+
.catch((error) => {
|
|
304
|
+
this.log.error('Error during subscription to EveHistoryEntries:', error);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
setInterval(async () => {
|
|
308
|
+
try {
|
|
309
|
+
const attributesEveCluster = await interactionClient.getMultipleAttributes({
|
|
310
|
+
attributes: [{ clusterId: EveHistoryCluster.id }],
|
|
311
|
+
});
|
|
312
|
+
this.log.info('\x1b[97;45mEve device: ' + name + '\x1b[40;0m');
|
|
313
|
+
|
|
314
|
+
attributesEveCluster.forEach((attribute) => {
|
|
315
|
+
if (attribute.path.attributeId === EveHistoryCluster.attributes.ConfigDataGet.id) {
|
|
316
|
+
const data = Buffer.from(attribute.value);
|
|
317
|
+
logMessage = `ConfigDataGet(${data.length}): [${data.toHex()}]`;
|
|
318
|
+
this.log.info(logMessage);
|
|
319
|
+
this.log.info('*' + history.decodeConfigData(data));
|
|
320
|
+
fs.appendFileSync(name + '.config.log', logMessage + '\n');
|
|
321
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.HistoryStatus.id) {
|
|
322
|
+
logMessage = history.decodeHistoryStatus(Buffer.from(attribute.value));
|
|
323
|
+
this.log.info(logMessage);
|
|
324
|
+
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
325
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.HistoryEntries.id) {
|
|
326
|
+
const bufferHistoryEntries = Buffer.from(attribute.value);
|
|
327
|
+
for (let i = 0; i < bufferHistoryEntries.length; ) {
|
|
328
|
+
const bufferHistoryEntry = Buffer.copyBytesFrom(bufferHistoryEntries, i, bufferHistoryEntries.readUInt8(i));
|
|
329
|
+
i += bufferHistoryEntries.readUInt8(i);
|
|
330
|
+
history.decodeHistoryEntry(bufferHistoryEntry);
|
|
331
|
+
this.log.info((logMessage = history.historyEntryToString(bufferHistoryEntry)));
|
|
332
|
+
fs.appendFileSync(name + '.log', logMessage + '\n');
|
|
333
|
+
}
|
|
334
|
+
history.writeHistoryFile();
|
|
335
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.TimesOpened.id) {
|
|
336
|
+
this.log.info(`TimesOpened: ${attribute.value}`);
|
|
337
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.LastEvent.id) {
|
|
338
|
+
this.log.info(`LastEvent: ${attribute.value}=${history.secsToDateString(attribute.value + history.getInitialTime() - history.getTimeOffset())}`);
|
|
339
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.ResetTotal.id) {
|
|
340
|
+
this.log.info(`ResetTotal: ${attribute.value}=${history.secsToDateStringSinceEveEpoch(attribute.value)}`);
|
|
341
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.Voltage.id) {
|
|
342
|
+
this.log.info(`Voltage: ${attribute.value}`);
|
|
343
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.Current.id) {
|
|
344
|
+
this.log.info(`Current: ${attribute.value}`);
|
|
345
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.Consumption.id) {
|
|
346
|
+
this.log.info(`Consumption: ${attribute.value}`);
|
|
347
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.TotalConsumption.id) {
|
|
348
|
+
this.log.info(`TotalConsumption: ${attribute.value}`);
|
|
349
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.ChildLock.id) {
|
|
350
|
+
this.log.info(`ChildLock: ${attribute.value}`);
|
|
351
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.MotionSensitivity.id) {
|
|
352
|
+
this.log.info(`MotionSensitivity: ${attribute.value}`);
|
|
353
|
+
} else if (attribute.path.attributeId === EveHistoryCluster.attributes.RLoc.id) {
|
|
354
|
+
this.log.info((logMessage = `RLoc: 0x${attribute.value.toString(16)}`));
|
|
355
|
+
} else {
|
|
356
|
+
if (attribute.path.attributeId >= 0x130a0000) {
|
|
357
|
+
this.log.info(`Unknown attribute ${attribute.path.attributeName} type: ${typeof attribute.value} value: [${attribute.value.toString(16)}]${attribute.value}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
} catch (error) {
|
|
362
|
+
console.error(error);
|
|
363
|
+
}
|
|
364
|
+
}, 30000);
|
|
365
|
+
} else {
|
|
366
|
+
this.log.info(`EveHistory not found on ${device.id} name: ${device.name}`);
|
|
293
367
|
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
368
|
+
}); // devices.forEach(async device => {
|
|
369
|
+
}); // nodes.forEach(async nodeId => {
|
|
370
|
+
|
|
371
|
+
if (hasParameter('unpairall')) {
|
|
372
|
+
nodes.forEach(async (nodeId) => {
|
|
373
|
+
await commissioningController.removeNode(nodeId);
|
|
374
|
+
});
|
|
375
|
+
process.exit(0);
|
|
297
376
|
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (hasParameter('unpairall')) {
|
|
302
|
-
nodes.forEach(async (nodeId) => {
|
|
303
|
-
await commissioningController.removeNode(nodeId);
|
|
304
|
-
});
|
|
305
|
-
process.exit(0);
|
|
306
|
-
}
|
|
377
|
+
}
|
|
378
|
+
*/
|
|
307
379
|
}
|
|
308
|
-
*/
|
|
309
380
|
//# sourceMappingURL=matterbridgeController.js.map
|