matterbridge 2.2.8-dev.1 → 3.0.0-edge.2
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 +31 -2
- package/dist/cluster/export.js +205 -1
- package/dist/matterbridge.js +43 -13
- package/dist/matterbridgeBehaviors.js +88 -10
- package/dist/matterbridgeDeviceTypes.js +145 -121
- package/dist/matterbridgeEndpoint.js +77 -25
- package/dist/matterbridgeEndpointHelpers.js +21 -18
- package/frontend/build/asset-manifest.json +3 -3
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/js/{main.eb2f3e01.js → main.fe57dcc8.js} +3 -3
- package/frontend/build/static/js/{main.eb2f3e01.js.map → main.fe57dcc8.js.map} +1 -1
- package/npm-shrinkwrap.json +44 -44
- package/package.json +2 -2
- /package/frontend/build/static/js/{main.eb2f3e01.js.LICENSE.txt → main.fe57dcc8.js.LICENSE.txt} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -29,7 +29,37 @@ Features:
|
|
|
29
29
|
- It is possible to choose the method: GET or POST.
|
|
30
30
|
- The webhook can be tested directly in the frontend.
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Breaking changes
|
|
33
|
+
|
|
34
|
+
Matter 1.4
|
|
35
|
+
|
|
36
|
+
New device types:
|
|
37
|
+
|
|
38
|
+
- onOffMountedSwitch: Mounted On/Off Control (an onOff switch without client cluster!).
|
|
39
|
+
- dimmableMountedSwitch: Mounted Dimmable Load Control (a dimmer switch without client cluster!).
|
|
40
|
+
|
|
41
|
+
Modified clusters:
|
|
42
|
+
|
|
43
|
+
- OccupancySensing cluster.
|
|
44
|
+
|
|
45
|
+
## [3.0.0] - 2025-04-??
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- [addEndpoint]: Added an error handler with deep stack on aggregatorNode.add() and serverNode.add() calls.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- [deviceTypes]: Updated device types to Matter 1.4
|
|
54
|
+
- [matter.js]: Update to 0.13.0-alpha.0-20250405-7fc7db48.
|
|
55
|
+
- [matter.js]: Update to 0.13.0-alpha.0-20250408-c916c7e8.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- [doorLock]: Fixed supportedOperatingModes inverted bitmap (Thanks Apollon).
|
|
60
|
+
- [DevicesIcon]: Fixed rendering of leak freeze and rain sensors.
|
|
61
|
+
|
|
62
|
+
## [2.2.8] - 2025-04-08
|
|
33
63
|
|
|
34
64
|
### Added
|
|
35
65
|
|
|
@@ -44,7 +74,6 @@ Features:
|
|
|
44
74
|
### Fixed
|
|
45
75
|
|
|
46
76
|
- [homepage]: Fixed warning log for homepage property in package.json.
|
|
47
|
-
- [DevicesIcon]: Fixed rendering of rain, freeze and leak sensors.
|
|
48
77
|
|
|
49
78
|
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
50
79
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
package/dist/cluster/export.js
CHANGED
|
@@ -1 +1,205 @@
|
|
|
1
|
-
|
|
1
|
+
import { ModeBase } from '@matter/main/clusters/mode-base';
|
|
2
|
+
import { Attribute, BitFlag, ClusterRegistry, Command, Event, EventPriority, FixedAttribute, MutableCluster, OptionalAttribute, OptionalCommand, OptionalEvent, TlvArray, TlvEnum, TlvField, TlvNoArguments, TlvNullable, TlvObject, TlvOptionalField, TlvString, TlvUInt32, TlvUInt8, TlvVendorId, WritableAttribute, } from '@matter/main/types';
|
|
3
|
+
import { OperationalState as OperationalStateNamespace } from '@matter/main/clusters/operational-state';
|
|
4
|
+
export var RvcRunMode;
|
|
5
|
+
(function (RvcRunMode) {
|
|
6
|
+
let Feature;
|
|
7
|
+
(function (Feature) {
|
|
8
|
+
Feature["OnOff"] = "OnOff";
|
|
9
|
+
})(Feature = RvcRunMode.Feature || (RvcRunMode.Feature = {}));
|
|
10
|
+
let ModeTag;
|
|
11
|
+
(function (ModeTag) {
|
|
12
|
+
ModeTag[ModeTag["Auto"] = 0] = "Auto";
|
|
13
|
+
ModeTag[ModeTag["Quick"] = 1] = "Quick";
|
|
14
|
+
ModeTag[ModeTag["Quiet"] = 2] = "Quiet";
|
|
15
|
+
ModeTag[ModeTag["LowNoise"] = 3] = "LowNoise";
|
|
16
|
+
ModeTag[ModeTag["LowEnergy"] = 4] = "LowEnergy";
|
|
17
|
+
ModeTag[ModeTag["Vacation"] = 5] = "Vacation";
|
|
18
|
+
ModeTag[ModeTag["Min"] = 6] = "Min";
|
|
19
|
+
ModeTag[ModeTag["Max"] = 7] = "Max";
|
|
20
|
+
ModeTag[ModeTag["Night"] = 8] = "Night";
|
|
21
|
+
ModeTag[ModeTag["Day"] = 9] = "Day";
|
|
22
|
+
ModeTag[ModeTag["Idle"] = 16384] = "Idle";
|
|
23
|
+
ModeTag[ModeTag["Cleaning"] = 16385] = "Cleaning";
|
|
24
|
+
ModeTag[ModeTag["Mapping"] = 16386] = "Mapping";
|
|
25
|
+
})(ModeTag = RvcRunMode.ModeTag || (RvcRunMode.ModeTag = {}));
|
|
26
|
+
RvcRunMode.TlvModeTagStruct = TlvObject({
|
|
27
|
+
mfgCode: TlvOptionalField(0, TlvVendorId),
|
|
28
|
+
value: TlvField(1, TlvEnum()),
|
|
29
|
+
});
|
|
30
|
+
RvcRunMode.TlvModeOption = TlvObject({
|
|
31
|
+
label: TlvField(0, TlvString.bound({ maxLength: 64 })),
|
|
32
|
+
mode: TlvField(1, TlvUInt8),
|
|
33
|
+
modeTags: TlvField(2, TlvArray(RvcRunMode.TlvModeTagStruct, { maxLength: 8 })),
|
|
34
|
+
});
|
|
35
|
+
let ModeChangeStatus;
|
|
36
|
+
(function (ModeChangeStatus) {
|
|
37
|
+
ModeChangeStatus[ModeChangeStatus["Stuck"] = 65] = "Stuck";
|
|
38
|
+
ModeChangeStatus[ModeChangeStatus["DustBinMissing"] = 66] = "DustBinMissing";
|
|
39
|
+
ModeChangeStatus[ModeChangeStatus["DustBinFull"] = 67] = "DustBinFull";
|
|
40
|
+
ModeChangeStatus[ModeChangeStatus["WaterTankEmpty"] = 68] = "WaterTankEmpty";
|
|
41
|
+
ModeChangeStatus[ModeChangeStatus["WaterTankMissing"] = 69] = "WaterTankMissing";
|
|
42
|
+
ModeChangeStatus[ModeChangeStatus["WaterTankLidOpen"] = 70] = "WaterTankLidOpen";
|
|
43
|
+
ModeChangeStatus[ModeChangeStatus["MopCleaningPadMissing"] = 71] = "MopCleaningPadMissing";
|
|
44
|
+
ModeChangeStatus[ModeChangeStatus["BatteryLow"] = 72] = "BatteryLow";
|
|
45
|
+
})(ModeChangeStatus = RvcRunMode.ModeChangeStatus || (RvcRunMode.ModeChangeStatus = {}));
|
|
46
|
+
RvcRunMode.OnOffComponent = MutableCluster.Component({
|
|
47
|
+
attributes: {
|
|
48
|
+
startUpMode: WritableAttribute(0x2, TlvNullable(TlvUInt8), { persistent: true }),
|
|
49
|
+
onMode: WritableAttribute(0x3, TlvNullable(TlvUInt8), { persistent: true, default: null }),
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
RvcRunMode.Base = MutableCluster.Component({
|
|
53
|
+
id: 0x54,
|
|
54
|
+
name: 'RvcRunMode',
|
|
55
|
+
revision: 3,
|
|
56
|
+
features: {
|
|
57
|
+
onOff: BitFlag(0),
|
|
58
|
+
},
|
|
59
|
+
attributes: {
|
|
60
|
+
supportedModes: FixedAttribute(0x0, TlvArray(RvcRunMode.TlvModeOption, { minLength: 2, maxLength: 255 }), { default: [] }),
|
|
61
|
+
currentMode: Attribute(0x1, TlvUInt8, { persistent: true }),
|
|
62
|
+
},
|
|
63
|
+
commands: {
|
|
64
|
+
changeToMode: Command(0x0, ModeBase.TlvChangeToModeRequest, 0x1, ModeBase.TlvChangeToModeResponse),
|
|
65
|
+
},
|
|
66
|
+
extensions: MutableCluster.Extensions({ flags: { onOff: true }, component: RvcRunMode.OnOffComponent }),
|
|
67
|
+
});
|
|
68
|
+
RvcRunMode.ClusterInstance = MutableCluster(RvcRunMode.Base);
|
|
69
|
+
RvcRunMode.Cluster = RvcRunMode.ClusterInstance;
|
|
70
|
+
RvcRunMode.Complete = RvcRunMode.Cluster;
|
|
71
|
+
})(RvcRunMode || (RvcRunMode = {}));
|
|
72
|
+
export const RvcRunModeCluster = RvcRunMode.Cluster;
|
|
73
|
+
ClusterRegistry.register(RvcRunMode.Complete);
|
|
74
|
+
export var RvcCleanMode;
|
|
75
|
+
(function (RvcCleanMode) {
|
|
76
|
+
let Feature;
|
|
77
|
+
(function (Feature) {
|
|
78
|
+
Feature["OnOff"] = "OnOff";
|
|
79
|
+
})(Feature = RvcCleanMode.Feature || (RvcCleanMode.Feature = {}));
|
|
80
|
+
let ModeTag;
|
|
81
|
+
(function (ModeTag) {
|
|
82
|
+
ModeTag[ModeTag["Auto"] = 0] = "Auto";
|
|
83
|
+
ModeTag[ModeTag["Quick"] = 1] = "Quick";
|
|
84
|
+
ModeTag[ModeTag["Quiet"] = 2] = "Quiet";
|
|
85
|
+
ModeTag[ModeTag["LowNoise"] = 3] = "LowNoise";
|
|
86
|
+
ModeTag[ModeTag["LowEnergy"] = 4] = "LowEnergy";
|
|
87
|
+
ModeTag[ModeTag["Vacation"] = 5] = "Vacation";
|
|
88
|
+
ModeTag[ModeTag["Min"] = 6] = "Min";
|
|
89
|
+
ModeTag[ModeTag["Max"] = 7] = "Max";
|
|
90
|
+
ModeTag[ModeTag["Night"] = 8] = "Night";
|
|
91
|
+
ModeTag[ModeTag["Day"] = 9] = "Day";
|
|
92
|
+
ModeTag[ModeTag["DeepClean"] = 16384] = "DeepClean";
|
|
93
|
+
ModeTag[ModeTag["Vacuum"] = 16385] = "Vacuum";
|
|
94
|
+
ModeTag[ModeTag["Mop"] = 16386] = "Mop";
|
|
95
|
+
})(ModeTag = RvcCleanMode.ModeTag || (RvcCleanMode.ModeTag = {}));
|
|
96
|
+
RvcCleanMode.TlvModeTagStruct = TlvObject({
|
|
97
|
+
mfgCode: TlvOptionalField(0, TlvVendorId),
|
|
98
|
+
value: TlvField(1, TlvEnum()),
|
|
99
|
+
});
|
|
100
|
+
RvcCleanMode.TlvModeOption = TlvObject({
|
|
101
|
+
label: TlvField(0, TlvString.bound({ maxLength: 64 })),
|
|
102
|
+
mode: TlvField(1, TlvUInt8),
|
|
103
|
+
modeTags: TlvField(2, TlvArray(RvcCleanMode.TlvModeTagStruct, { maxLength: 8 })),
|
|
104
|
+
});
|
|
105
|
+
let ModeChangeStatus;
|
|
106
|
+
(function (ModeChangeStatus) {
|
|
107
|
+
ModeChangeStatus[ModeChangeStatus["CleaningInProgress"] = 64] = "CleaningInProgress";
|
|
108
|
+
})(ModeChangeStatus = RvcCleanMode.ModeChangeStatus || (RvcCleanMode.ModeChangeStatus = {}));
|
|
109
|
+
RvcCleanMode.OnOffComponent = MutableCluster.Component({
|
|
110
|
+
attributes: {
|
|
111
|
+
startUpMode: WritableAttribute(0x2, TlvNullable(TlvUInt8), { persistent: true }),
|
|
112
|
+
onMode: WritableAttribute(0x3, TlvNullable(TlvUInt8), { persistent: true, default: null }),
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
RvcCleanMode.Base = MutableCluster.Component({
|
|
116
|
+
id: 0x55,
|
|
117
|
+
name: 'RvcCleanMode',
|
|
118
|
+
revision: 3,
|
|
119
|
+
features: {
|
|
120
|
+
onOff: BitFlag(0),
|
|
121
|
+
},
|
|
122
|
+
attributes: {
|
|
123
|
+
supportedModes: FixedAttribute(0x0, TlvArray(RvcCleanMode.TlvModeOption, { minLength: 2, maxLength: 255 }), { default: [] }),
|
|
124
|
+
currentMode: Attribute(0x1, TlvUInt8, { persistent: true }),
|
|
125
|
+
},
|
|
126
|
+
commands: {
|
|
127
|
+
changeToMode: Command(0x0, ModeBase.TlvChangeToModeRequest, 0x1, ModeBase.TlvChangeToModeResponse),
|
|
128
|
+
},
|
|
129
|
+
extensions: MutableCluster.Extensions({ flags: { onOff: true }, component: RvcCleanMode.OnOffComponent }),
|
|
130
|
+
});
|
|
131
|
+
RvcCleanMode.ClusterInstance = MutableCluster(RvcCleanMode.Base);
|
|
132
|
+
RvcCleanMode.Cluster = RvcCleanMode.ClusterInstance;
|
|
133
|
+
RvcCleanMode.Complete = RvcCleanMode.Cluster;
|
|
134
|
+
})(RvcCleanMode || (RvcCleanMode = {}));
|
|
135
|
+
export const RvcCleanModeCluster = RvcCleanMode.Cluster;
|
|
136
|
+
ClusterRegistry.register(RvcCleanMode.Complete);
|
|
137
|
+
export var RvcOperationalState;
|
|
138
|
+
(function (RvcOperationalState) {
|
|
139
|
+
let OperationalState;
|
|
140
|
+
(function (OperationalState) {
|
|
141
|
+
OperationalState[OperationalState["Stopped"] = 0] = "Stopped";
|
|
142
|
+
OperationalState[OperationalState["Running"] = 1] = "Running";
|
|
143
|
+
OperationalState[OperationalState["Paused"] = 2] = "Paused";
|
|
144
|
+
OperationalState[OperationalState["Error"] = 3] = "Error";
|
|
145
|
+
OperationalState[OperationalState["SeekingCharger"] = 64] = "SeekingCharger";
|
|
146
|
+
OperationalState[OperationalState["Charging"] = 65] = "Charging";
|
|
147
|
+
OperationalState[OperationalState["Docked"] = 66] = "Docked";
|
|
148
|
+
})(OperationalState = RvcOperationalState.OperationalState || (RvcOperationalState.OperationalState = {}));
|
|
149
|
+
RvcOperationalState.TlvOperationalStateStruct = TlvObject({
|
|
150
|
+
operationalStateId: TlvField(0, TlvEnum()),
|
|
151
|
+
operationalStateLabel: TlvOptionalField(1, TlvString.bound({ maxLength: 64 })),
|
|
152
|
+
});
|
|
153
|
+
let ErrorState;
|
|
154
|
+
(function (ErrorState) {
|
|
155
|
+
ErrorState[ErrorState["NoError"] = 0] = "NoError";
|
|
156
|
+
ErrorState[ErrorState["UnableToStartOrResume"] = 1] = "UnableToStartOrResume";
|
|
157
|
+
ErrorState[ErrorState["UnableToCompleteOperation"] = 2] = "UnableToCompleteOperation";
|
|
158
|
+
ErrorState[ErrorState["CommandInvalidInState"] = 3] = "CommandInvalidInState";
|
|
159
|
+
ErrorState[ErrorState["FailedToFindChargingDock"] = 64] = "FailedToFindChargingDock";
|
|
160
|
+
ErrorState[ErrorState["Stuck"] = 65] = "Stuck";
|
|
161
|
+
ErrorState[ErrorState["DustBinMissing"] = 66] = "DustBinMissing";
|
|
162
|
+
ErrorState[ErrorState["DustBinFull"] = 67] = "DustBinFull";
|
|
163
|
+
ErrorState[ErrorState["WaterTankEmpty"] = 68] = "WaterTankEmpty";
|
|
164
|
+
ErrorState[ErrorState["WaterTankMissing"] = 69] = "WaterTankMissing";
|
|
165
|
+
ErrorState[ErrorState["WaterTankLidOpen"] = 70] = "WaterTankLidOpen";
|
|
166
|
+
ErrorState[ErrorState["MopCleaningPadMissing"] = 71] = "MopCleaningPadMissing";
|
|
167
|
+
})(ErrorState = RvcOperationalState.ErrorState || (RvcOperationalState.ErrorState = {}));
|
|
168
|
+
RvcOperationalState.TlvErrorStateStruct = TlvObject({
|
|
169
|
+
errorStateId: TlvField(0, TlvEnum()),
|
|
170
|
+
errorStateLabel: TlvOptionalField(1, TlvString.bound({ maxLength: 64 })),
|
|
171
|
+
errorStateDetails: TlvOptionalField(2, TlvString.bound({ maxLength: 64 })),
|
|
172
|
+
});
|
|
173
|
+
RvcOperationalState.TlvOperationalCommandResponse = TlvObject({
|
|
174
|
+
commandResponseState: TlvField(0, RvcOperationalState.TlvErrorStateStruct),
|
|
175
|
+
});
|
|
176
|
+
RvcOperationalState.TlvOperationalErrorEvent = TlvObject({ errorState: TlvField(0, RvcOperationalState.TlvErrorStateStruct) });
|
|
177
|
+
RvcOperationalState.ClusterInstance = MutableCluster({
|
|
178
|
+
id: 0x61,
|
|
179
|
+
name: 'RvcOperationalState',
|
|
180
|
+
revision: 2,
|
|
181
|
+
attributes: {
|
|
182
|
+
phaseList: Attribute(0x0, TlvNullable(TlvArray(TlvString, { maxLength: 32 }))),
|
|
183
|
+
currentPhase: Attribute(0x1, TlvNullable(TlvUInt8)),
|
|
184
|
+
countdownTime: OptionalAttribute(0x2, TlvNullable(TlvUInt32.bound({ max: 259200 })), { default: null }),
|
|
185
|
+
operationalStateList: Attribute(0x3, TlvArray(RvcOperationalState.TlvOperationalStateStruct), { default: [] }),
|
|
186
|
+
operationalState: Attribute(0x4, TlvEnum()),
|
|
187
|
+
operationalError: Attribute(0x5, RvcOperationalState.TlvErrorStateStruct),
|
|
188
|
+
},
|
|
189
|
+
commands: {
|
|
190
|
+
pause: OptionalCommand(0x0, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
|
191
|
+
stop: OptionalCommand(0x1, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
|
192
|
+
start: OptionalCommand(0x2, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
|
193
|
+
resume: OptionalCommand(0x3, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
|
194
|
+
goHome: OptionalCommand(0x80, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
|
195
|
+
},
|
|
196
|
+
events: {
|
|
197
|
+
operationalError: Event(0x0, EventPriority.Critical, RvcOperationalState.TlvOperationalErrorEvent),
|
|
198
|
+
operationCompletion: OptionalEvent(0x1, EventPriority.Info, OperationalStateNamespace.TlvOperationCompletionEvent),
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
RvcOperationalState.Cluster = RvcOperationalState.ClusterInstance;
|
|
202
|
+
RvcOperationalState.Complete = RvcOperationalState.Cluster;
|
|
203
|
+
})(RvcOperationalState || (RvcOperationalState = {}));
|
|
204
|
+
export const RvcOperationalStateCluster = RvcOperationalState.Cluster;
|
|
205
|
+
ClusterRegistry.register(RvcOperationalState.Complete);
|
package/dist/matterbridge.js
CHANGED
|
@@ -2,6 +2,7 @@ import os from 'node:os';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { promises as fs } from 'node:fs';
|
|
4
4
|
import EventEmitter from 'node:events';
|
|
5
|
+
import { inspect } from 'node:util';
|
|
5
6
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN } from './logger/export.js';
|
|
6
7
|
import { NodeStorageManager } from './storage/export.js';
|
|
7
8
|
import { getParameter, getIntParameter, hasParameter, copyDirectory, withTimeout } from './utils/export.js';
|
|
@@ -306,30 +307,30 @@ export class Matterbridge extends EventEmitter {
|
|
|
306
307
|
if (hasParameter('matterlogger')) {
|
|
307
308
|
const level = getParameter('matterlogger');
|
|
308
309
|
if (level === 'debug') {
|
|
309
|
-
Logger.
|
|
310
|
+
Logger.level = MatterLogLevel.DEBUG;
|
|
310
311
|
}
|
|
311
312
|
else if (level === 'info') {
|
|
312
|
-
Logger.
|
|
313
|
+
Logger.level = MatterLogLevel.INFO;
|
|
313
314
|
}
|
|
314
315
|
else if (level === 'notice') {
|
|
315
|
-
Logger.
|
|
316
|
+
Logger.level = MatterLogLevel.NOTICE;
|
|
316
317
|
}
|
|
317
318
|
else if (level === 'warn') {
|
|
318
|
-
Logger.
|
|
319
|
+
Logger.level = MatterLogLevel.WARN;
|
|
319
320
|
}
|
|
320
321
|
else if (level === 'error') {
|
|
321
|
-
Logger.
|
|
322
|
+
Logger.level = MatterLogLevel.ERROR;
|
|
322
323
|
}
|
|
323
324
|
else if (level === 'fatal') {
|
|
324
|
-
Logger.
|
|
325
|
+
Logger.level = MatterLogLevel.FATAL;
|
|
325
326
|
}
|
|
326
327
|
else {
|
|
327
328
|
this.log.warn(`Invalid matter.js logger level: ${level}. Using default level "info".`);
|
|
328
|
-
Logger.
|
|
329
|
+
Logger.level = MatterLogLevel.INFO;
|
|
329
330
|
}
|
|
330
331
|
}
|
|
331
332
|
else {
|
|
332
|
-
Logger.
|
|
333
|
+
Logger.level = (await this.nodeContext.get('matterLogLevel', this.matterbridgeInformation.shellyBoard ? MatterLogLevel.NOTICE : MatterLogLevel.INFO));
|
|
333
334
|
}
|
|
334
335
|
Logger.format = MatterLogFormat.ANSI;
|
|
335
336
|
Logger.setLogger('default', this.createMatterLogger());
|
|
@@ -1327,7 +1328,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1327
1328
|
}
|
|
1328
1329
|
this.startServerNode(plugin.serverNode);
|
|
1329
1330
|
plugin.reachabilityTimeout = setTimeout(() => {
|
|
1330
|
-
this.log.info(`Setting reachability to true for ${plg}${plugin.name}${
|
|
1331
|
+
this.log.info(`Setting reachability to true for ${plg}${plugin.name}${nf} type ${plugin.type} server node ${plugin.serverNode !== undefined} aggregator node ${plugin.aggregatorNode !== undefined} device ${plugin.device !== undefined}`);
|
|
1331
1332
|
if (plugin.type === 'DynamicPlatform' && plugin.aggregatorNode)
|
|
1332
1333
|
this.setAggregatorReachability(plugin.aggregatorNode, true);
|
|
1333
1334
|
this.frontend.wssSendRefreshRequired('reachability');
|
|
@@ -1430,6 +1431,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1430
1431
|
softwareVersionString: await storageContext.get('softwareVersionString'),
|
|
1431
1432
|
hardwareVersion: await storageContext.get('hardwareVersion'),
|
|
1432
1433
|
hardwareVersionString: await storageContext.get('hardwareVersionString'),
|
|
1434
|
+
reachable: true,
|
|
1433
1435
|
},
|
|
1434
1436
|
});
|
|
1435
1437
|
const sanitizeFabrics = (fabrics, resetSessions = false) => {
|
|
@@ -1638,18 +1640,46 @@ export class Matterbridge extends EventEmitter {
|
|
|
1638
1640
|
this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge aggregator node`);
|
|
1639
1641
|
if (!this.aggregatorNode)
|
|
1640
1642
|
this.log.error('Aggregator node not found for Matterbridge');
|
|
1641
|
-
|
|
1643
|
+
try {
|
|
1644
|
+
await this.aggregatorNode?.add(device);
|
|
1645
|
+
}
|
|
1646
|
+
catch (error) {
|
|
1647
|
+
const errorMessage = error instanceof Error ? error.message : '';
|
|
1648
|
+
const errorStack = error instanceof Error ? error.stack : '';
|
|
1649
|
+
const errorDebug = inspect(error, { depth: 10 });
|
|
1650
|
+
this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) for plugin ${plg}${pluginName}${er}: ${error} ${errorMessage} ${errorStack} ${errorDebug}`);
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1642
1653
|
}
|
|
1643
1654
|
else if (this.bridgeMode === 'childbridge') {
|
|
1644
1655
|
if (plugin.type === 'AccessoryPlatform') {
|
|
1645
|
-
|
|
1656
|
+
try {
|
|
1657
|
+
this.log.debug(`Creating endpoint ${dev}${device.deviceName}${db} for AccessoryPlatform plugin ${plg}${plugin.name}${db} server node`);
|
|
1658
|
+
await this.createAccessoryPlugin(plugin, device);
|
|
1659
|
+
}
|
|
1660
|
+
catch (error) {
|
|
1661
|
+
const errorMessage = error instanceof Error ? error.message : '';
|
|
1662
|
+
const errorStack = error instanceof Error ? error.stack : '';
|
|
1663
|
+
const errorDebug = inspect(error, { depth: 10 });
|
|
1664
|
+
this.log.error(`Error creating endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) for AccessoryPlatform plugin ${plg}${pluginName}${er} server node: ${error} ${errorMessage} ${errorStack} ${errorDebug}`);
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1646
1667
|
}
|
|
1647
1668
|
if (plugin.type === 'DynamicPlatform') {
|
|
1648
1669
|
plugin.locked = true;
|
|
1649
|
-
this.log.debug(`Adding bridged endpoint ${
|
|
1670
|
+
this.log.debug(`Adding bridged endpoint ${dev}${device.deviceName}${db} for DynamicPlatform plugin ${plg}${plugin.name}${db} aggregator node`);
|
|
1650
1671
|
if (!plugin.aggregatorNode)
|
|
1651
1672
|
this.log.error(`Aggregator node not found for plugin ${plg}${plugin.name}${db}`);
|
|
1652
|
-
|
|
1673
|
+
try {
|
|
1674
|
+
await plugin.aggregatorNode?.add(device);
|
|
1675
|
+
}
|
|
1676
|
+
catch (error) {
|
|
1677
|
+
const errorMessage = error instanceof Error ? error.message : '';
|
|
1678
|
+
const errorStack = error instanceof Error ? error.stack : '';
|
|
1679
|
+
const errorDebug = inspect(error, { depth: 10 });
|
|
1680
|
+
this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) for DynamicPlatform plugin ${plg}${pluginName}${er} aggregator node: ${error} ${errorMessage} ${errorStack} ${errorDebug}`);
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1653
1683
|
}
|
|
1654
1684
|
}
|
|
1655
1685
|
if (plugin.registeredDevices !== undefined)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Behavior } from '@matter/main';
|
|
1
|
+
import { Behavior, ClusterBehavior } from '@matter/main';
|
|
2
|
+
import { Status } from '@matter/main/types';
|
|
2
3
|
import { BooleanStateConfiguration } from '@matter/main/clusters/boolean-state-configuration';
|
|
3
4
|
import { ColorControl } from '@matter/main/clusters/color-control';
|
|
4
5
|
import { FanControl } from '@matter/main/clusters/fan-control';
|
|
@@ -14,11 +15,15 @@ import { ColorControlServer } from '@matter/main/behaviors/color-control';
|
|
|
14
15
|
import { WindowCoveringServer } from '@matter/main/behaviors/window-covering';
|
|
15
16
|
import { DoorLockServer } from '@matter/main/behaviors/door-lock';
|
|
16
17
|
import { FanControlServer } from '@matter/main/behaviors/fan-control';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
18
|
+
import { ThermostatBehavior } from '@matter/main/behaviors/thermostat';
|
|
19
|
+
import { ValveConfigurationAndControlBehavior } from '@matter/main/behaviors/valve-configuration-and-control';
|
|
19
20
|
import { ModeSelectServer } from '@matter/main/behaviors/mode-select';
|
|
20
21
|
import { SmokeCoAlarmServer } from '@matter/main/behaviors/smoke-co-alarm';
|
|
21
22
|
import { SwitchServer } from '@matter/main/behaviors/switch';
|
|
23
|
+
import { RvcCleanMode } from 'matterbridge/cluster';
|
|
24
|
+
import { RvcRunMode } from 'matterbridge/cluster';
|
|
25
|
+
import { RvcOperationalState } from 'matterbridge/cluster';
|
|
26
|
+
import { OperationalState } from '@matter/main/clusters/operational-state';
|
|
22
27
|
export class MatterbridgeBehaviorDevice {
|
|
23
28
|
log;
|
|
24
29
|
commandHandler;
|
|
@@ -292,7 +297,7 @@ export class MatterbridgeFanControlServer extends FanControlServer.with(FanContr
|
|
|
292
297
|
super.step({ direction, wrap, lowestOff });
|
|
293
298
|
}
|
|
294
299
|
}
|
|
295
|
-
export class MatterbridgeThermostatServer extends
|
|
300
|
+
export class MatterbridgeThermostatServer extends ThermostatBehavior.with(Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode) {
|
|
296
301
|
async setpointRaiseLower({ mode, amount }) {
|
|
297
302
|
const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
|
|
298
303
|
device.setpointRaiseLower({ mode, amount });
|
|
@@ -310,19 +315,24 @@ export class MatterbridgeThermostatServer extends ThermostatServer.with(Thermost
|
|
|
310
315
|
this.state.occupiedCoolingSetpoint = setpoint * 100;
|
|
311
316
|
device.log.debug('Set occupiedCoolingSetpoint to:', setpoint);
|
|
312
317
|
}
|
|
313
|
-
super.setpointRaiseLower({ mode, amount });
|
|
314
318
|
}
|
|
315
319
|
}
|
|
316
|
-
export class MatterbridgeValveConfigurationAndControlServer extends
|
|
317
|
-
|
|
320
|
+
export class MatterbridgeValveConfigurationAndControlServer extends ValveConfigurationAndControlBehavior.with(ValveConfigurationAndControl.Feature.Level) {
|
|
321
|
+
initialize() {
|
|
322
|
+
}
|
|
323
|
+
open({ openDuration, targetLevel }) {
|
|
318
324
|
const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
|
|
325
|
+
device.log.debug(`Command open called with openDuration: ${openDuration} targetLevel: ${targetLevel}`);
|
|
319
326
|
device.open({ openDuration, targetLevel });
|
|
320
|
-
|
|
327
|
+
this.state.targetLevel = targetLevel ?? 100;
|
|
328
|
+
this.state.currentLevel = targetLevel ?? 100;
|
|
321
329
|
}
|
|
322
|
-
|
|
330
|
+
close() {
|
|
323
331
|
const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
|
|
332
|
+
device.log.debug(`Command close called`);
|
|
324
333
|
device.close();
|
|
325
|
-
|
|
334
|
+
this.state.targetLevel = 0;
|
|
335
|
+
this.state.currentLevel = 0;
|
|
326
336
|
}
|
|
327
337
|
}
|
|
328
338
|
export class MatterbridgeSmokeCoAlarmServer extends SmokeCoAlarmServer.with(SmokeCoAlarm.Feature.SmokeAlarm, SmokeCoAlarm.Feature.CoAlarm) {
|
|
@@ -343,3 +353,71 @@ export class MatterbridgeSwitchServer extends SwitchServer {
|
|
|
343
353
|
initialize() {
|
|
344
354
|
}
|
|
345
355
|
}
|
|
356
|
+
export const RvcRunModeBehavior = ClusterBehavior.withInterface().for(RvcRunMode.Cluster);
|
|
357
|
+
export class MatterbridgeRvcRunModeServer extends RvcRunModeBehavior.with(RvcRunMode.Feature.OnOff) {
|
|
358
|
+
initialize() {
|
|
359
|
+
}
|
|
360
|
+
changeToMode({ newMode }) {
|
|
361
|
+
const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
|
|
362
|
+
device.changeToMode({ newMode });
|
|
363
|
+
this.state.currentMode = newMode;
|
|
364
|
+
console.log('MatterbridgeRvcRunModeServer changeToMode called with newMode:', newMode);
|
|
365
|
+
return { status: Status.Success, statusText: 'Success' };
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
export const RvcCleanModeBehavior = ClusterBehavior.withInterface().for(RvcCleanMode.Cluster);
|
|
369
|
+
export class MatterbridgeRvcCleanModeServer extends RvcCleanModeBehavior.with(RvcRunMode.Feature.OnOff) {
|
|
370
|
+
initialize() {
|
|
371
|
+
}
|
|
372
|
+
changeToMode({ newMode }) {
|
|
373
|
+
const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
|
|
374
|
+
device.changeToMode({ newMode });
|
|
375
|
+
this.state.currentMode = newMode;
|
|
376
|
+
console.log('MatterbridgeRvcCleanModeServer changeToMode called with newMode:', newMode);
|
|
377
|
+
return { status: Status.Success, statusText: 'Success' };
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
export const RvcOperationalStateBehavior = ClusterBehavior.withInterface().for(RvcOperationalState.Cluster);
|
|
381
|
+
export class MatterbridgeRvcOperationalStateServer extends RvcOperationalStateBehavior {
|
|
382
|
+
initialize() {
|
|
383
|
+
console.log('MatterbridgeRvcOperationalStateServer initialized: setting operational state to Docked');
|
|
384
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
|
385
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error' };
|
|
386
|
+
this.reactTo(this.agent.get(OnOffServer).events.onOff$Changed, this.handleOnOffChange);
|
|
387
|
+
}
|
|
388
|
+
handleOnOffChange(onOff) {
|
|
389
|
+
if (onOff) {
|
|
390
|
+
console.log('OnOffServer changed to ON: setting operational state to Running');
|
|
391
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 2;
|
|
392
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Running;
|
|
393
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error' };
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
console.log('OnOffServer changed to OFF: setting operational state to Docked');
|
|
397
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
|
398
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
|
399
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error' };
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
pause() {
|
|
403
|
+
console.log('MatterbridgeRvcOperationalStateServer: pause called setting operational state to Paused and currentMode to Idle');
|
|
404
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
|
405
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Paused;
|
|
406
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error' };
|
|
407
|
+
return { commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error' } };
|
|
408
|
+
}
|
|
409
|
+
resume() {
|
|
410
|
+
console.log('MatterbridgeRvcOperationalStateServer: resume called setting operational state to Running and currentMode to Cleaning');
|
|
411
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 2;
|
|
412
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Running;
|
|
413
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error' };
|
|
414
|
+
return { commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error' } };
|
|
415
|
+
}
|
|
416
|
+
goHome() {
|
|
417
|
+
console.log('MatterbridgeRvcOperationalStateServer: go home called setting operational state to Docked and currentMode to Idle');
|
|
418
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
|
419
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
|
420
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error' };
|
|
421
|
+
return { commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error' } };
|
|
422
|
+
}
|
|
423
|
+
}
|