matterbridge-example-dynamic-platform 1.1.9 → 1.2.0-edge.5
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 +18 -0
- package/dist/appliances.js +452 -0
- package/dist/implementations/carbonMonoxideConcentrationMeasurement.js +113 -0
- package/dist/implementations/ovenCavityOperationalStateCluster.js +30 -0
- package/dist/implementations/roboticVacuumCleanerClusters.js +71 -0
- package/dist/platform.js +41 -2
- package/dist/robot.js +208 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -8,6 +8,24 @@ If you like this project and find it useful, please consider giving it a star on
|
|
8
8
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="120">
|
9
9
|
</a>
|
10
10
|
|
11
|
+
## [1.2.0] - 2025-04-08
|
12
|
+
|
13
|
+
### Added
|
14
|
+
|
15
|
+
- [platform]: Added Robot Vacuum Cleaner device (supported by SmartThings, Alexa, Home Assistant and Apple Home).
|
16
|
+
- [platform]: Added Laundry Washer deice (supported by SmartThings, Alexa and Home Assistant).
|
17
|
+
- [platform]: Added Dishwasher device (supported by SmartThings, Alexa and Home Assistant).
|
18
|
+
- [platform]: Added Temperature Controlled Cabinet Cooler device (supported by SmartThings, Alexa and Home Assistant).
|
19
|
+
- [platform]: Added Temperature Controlled Cabinet Heater device (supported by SmartThings, Alexa and Home Assistant).
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
|
23
|
+
- [package]: Updated dependencies.
|
24
|
+
|
25
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
26
|
+
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
27
|
+
</a>
|
28
|
+
|
11
29
|
## [1.1.9] - 2025-04-07
|
12
30
|
|
13
31
|
### Added
|
@@ -0,0 +1,452 @@
|
|
1
|
+
import { DeviceClasses, DeviceTypeDefinition, MatterbridgeEndpoint, Status, Matterbridge, VendorId, DeviceTypeId, MatterbridgeServer, smokeCoAlarm, MatterbridgeOnOffServer, } from 'matterbridge';
|
2
|
+
import { ClusterBehavior, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, EndpointServer, logEndpoint } from 'matterbridge/matter';
|
3
|
+
import { Identify, OperationalState, OnOff, TemperatureControl, DishwasherAlarm, DishwasherMode, LaundryWasherControls, LaundryWasherMode, LaundryDryerControls, TemperatureMeasurement, OvenMode, RefrigeratorAndTemperatureControlledCabinetMode, } from 'matterbridge/matter/clusters';
|
4
|
+
import { DishwasherAlarmServer, LaundryDryerControlsServer, LaundryWasherControlsServer, OperationalStateBehavior, TemperatureControlBehavior, } from 'matterbridge/matter/behaviors';
|
5
|
+
import { OvenCavityOperationalState } from './implementations/ovenCavityOperationalStateCluster.js';
|
6
|
+
import { AnsiLogger } from 'matterbridge/logger';
|
7
|
+
import { Robot } from './robot.js';
|
8
|
+
export class Appliances extends MatterbridgeEndpoint {
|
9
|
+
static temperatureControlledCabinetCooler = DeviceTypeDefinition({
|
10
|
+
name: 'MA-temperaturecontrolledcabinetcooler',
|
11
|
+
code: 0x71,
|
12
|
+
deviceClass: DeviceClasses.Simple,
|
13
|
+
revision: 3,
|
14
|
+
requiredServerClusters: [TemperatureControl.Cluster.id, RefrigeratorAndTemperatureControlledCabinetMode.Cluster.id],
|
15
|
+
optionalServerClusters: [TemperatureMeasurement.Cluster.id],
|
16
|
+
});
|
17
|
+
static temperatureControlledCabinetHeater = DeviceTypeDefinition({
|
18
|
+
name: 'MA-temperaturecontrolledcabinetheater',
|
19
|
+
code: 0x71,
|
20
|
+
deviceClass: DeviceClasses.Simple,
|
21
|
+
revision: 3,
|
22
|
+
requiredServerClusters: [TemperatureControl.Cluster.id, OvenMode.Cluster.id, OvenCavityOperationalState.Cluster.id],
|
23
|
+
optionalServerClusters: [TemperatureMeasurement.Cluster.id],
|
24
|
+
});
|
25
|
+
static laundryWasher = DeviceTypeDefinition({
|
26
|
+
name: 'MA-laundrywasher',
|
27
|
+
code: 0x73,
|
28
|
+
deviceClass: DeviceClasses.Simple,
|
29
|
+
revision: 1,
|
30
|
+
requiredServerClusters: [OperationalState.Cluster.id],
|
31
|
+
optionalServerClusters: [Identify.Cluster.id, LaundryWasherMode.Cluster.id, OnOff.Cluster.id, LaundryWasherControls.Cluster.id, TemperatureControl.Cluster.id],
|
32
|
+
});
|
33
|
+
static laundryDryer = DeviceTypeDefinition({
|
34
|
+
name: 'MA-laundrydryer',
|
35
|
+
code: 0x7c,
|
36
|
+
deviceClass: DeviceClasses.Simple,
|
37
|
+
revision: 1,
|
38
|
+
requiredServerClusters: [OperationalState.Cluster.id],
|
39
|
+
optionalServerClusters: [Identify.Cluster.id, LaundryWasherMode.Cluster.id, OnOff.Cluster.id, LaundryDryerControls.Cluster.id, TemperatureControl.Cluster.id],
|
40
|
+
});
|
41
|
+
static dishwasher = DeviceTypeDefinition({
|
42
|
+
name: 'MA-dishwasher',
|
43
|
+
code: 0x75,
|
44
|
+
deviceClass: DeviceClasses.Simple,
|
45
|
+
revision: 1,
|
46
|
+
requiredServerClusters: [OperationalState.Cluster.id],
|
47
|
+
optionalServerClusters: [Identify.Cluster.id, OnOff.Cluster.id, TemperatureControl.Cluster.id, DishwasherMode.Cluster.id, DishwasherAlarm.Cluster.id],
|
48
|
+
});
|
49
|
+
constructor(deviceType, name, serial) {
|
50
|
+
super(deviceType, { uniqueStorageKey: `${name}-${serial}` });
|
51
|
+
if (deviceType.code === Appliances.laundryWasher.code) {
|
52
|
+
this.createDefaultIdentifyClusterServer();
|
53
|
+
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Laundry Washer');
|
54
|
+
this.createDeadFrontOnOffClusterServer();
|
55
|
+
this.createLevelTemperatureControlClusterServer(3, ['Cold', '30°', '40°', '60°', '80°']);
|
56
|
+
this.createDefaultLaundryWasherModeClusterServer();
|
57
|
+
this.createSpinLaundryWasherControlsClusterServer(3, ['400', '800', '1200', '1600']);
|
58
|
+
this.createDefaultOperationalStateClusterServer(OperationalState.OperationalStateEnum.Stopped);
|
59
|
+
}
|
60
|
+
else if (deviceType.code === Appliances.laundryDryer.code) {
|
61
|
+
this.createDefaultIdentifyClusterServer();
|
62
|
+
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Laundry Dryer');
|
63
|
+
this.createDeadFrontOnOffClusterServer();
|
64
|
+
this.createLevelTemperatureControlClusterServer(3, ['Cold', '30°', '40°', '60°', '80°']);
|
65
|
+
this.createDefaultLaundryWasherModeClusterServer();
|
66
|
+
this.createDefaultLaundryDryerControlsClusterServer(1);
|
67
|
+
this.createDefaultOperationalStateClusterServer(OperationalState.OperationalStateEnum.Stopped);
|
68
|
+
}
|
69
|
+
else if (deviceType.code === Appliances.dishwasher.code) {
|
70
|
+
this.createDefaultIdentifyClusterServer();
|
71
|
+
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Dishwasher');
|
72
|
+
this.createDeadFrontOnOffClusterServer();
|
73
|
+
this.createLevelTemperatureControlClusterServer(1, ['Cold', '30°', '40°', '60°']);
|
74
|
+
this.createDefaultDishwasherModeClusterServer();
|
75
|
+
this.createDefaultDishwasherAlarmClusterServer();
|
76
|
+
this.createDefaultOperationalStateClusterServer(OperationalState.OperationalStateEnum.Stopped);
|
77
|
+
}
|
78
|
+
else if (deviceType.name === Appliances.temperatureControlledCabinetCooler.name) {
|
79
|
+
this.createDefaultIdentifyClusterServer();
|
80
|
+
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Temperature Controlled Cabinet Cooler');
|
81
|
+
this.createLevelTemperatureControlClusterServer(1, ['Cold', 'Warm', 'Hot']);
|
82
|
+
this.createDefaultTemperatureMeasurementClusterServer(1500);
|
83
|
+
this.createDefaultRefrigeratorAndTemperatureControlledCabinetModeClusterServer(1);
|
84
|
+
}
|
85
|
+
else if (deviceType.name === Appliances.temperatureControlledCabinetHeater.name) {
|
86
|
+
this.createDefaultIdentifyClusterServer();
|
87
|
+
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Temperature Controlled Cabinet Heater');
|
88
|
+
this.createLevelTemperatureControlClusterServer(1, ['Cold', 'Warm', 'Hot']);
|
89
|
+
this.createDefaultTemperatureMeasurementClusterServer(2500);
|
90
|
+
this.createDefaultOvenModeClusterServer(3);
|
91
|
+
this.createDefaultOvenCavityOperationalStateClusterServer(OperationalState.OperationalStateEnum.Stopped);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
createDefaultOperationalStateClusterServer(operationalState = OperationalState.OperationalStateEnum.Stopped) {
|
95
|
+
this.behaviors.require(MatterbridgeOperationalStateServer, {
|
96
|
+
phaseList: [],
|
97
|
+
currentPhase: null,
|
98
|
+
operationalStateList: [
|
99
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Stopped, operationalStateLabel: 'Stopped' },
|
100
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Running, operationalStateLabel: 'Running' },
|
101
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Paused, operationalStateLabel: 'Paused' },
|
102
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Error, operationalStateLabel: 'Error' },
|
103
|
+
],
|
104
|
+
operationalState,
|
105
|
+
operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
106
|
+
});
|
107
|
+
return this;
|
108
|
+
}
|
109
|
+
createDefaultOvenCavityOperationalStateClusterServer(operationalState = OperationalState.OperationalStateEnum.Stopped) {
|
110
|
+
this.behaviors.require(OvenCavityOperationalStateServer, {
|
111
|
+
phaseList: [],
|
112
|
+
currentPhase: null,
|
113
|
+
operationalStateList: [
|
114
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Stopped, operationalStateLabel: 'Stopped' },
|
115
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Running, operationalStateLabel: 'Running' },
|
116
|
+
{ operationalStateId: OperationalState.OperationalStateEnum.Error, operationalStateLabel: 'Error' },
|
117
|
+
],
|
118
|
+
operationalState,
|
119
|
+
operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
120
|
+
});
|
121
|
+
return this;
|
122
|
+
}
|
123
|
+
createDefaultRefrigeratorAndTemperatureControlledCabinetModeClusterServer(currentMode) {
|
124
|
+
this.behaviors.require(RefrigeratorAndTemperatureControlledCabinetModeServer, {
|
125
|
+
supportedModes: [
|
126
|
+
{ label: 'RapidCool', mode: 1, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidCool }] },
|
127
|
+
{ label: 'RapidFreeze', mode: 2, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidFreeze }] },
|
128
|
+
],
|
129
|
+
currentMode,
|
130
|
+
});
|
131
|
+
return this;
|
132
|
+
}
|
133
|
+
createDefaultDishwasherModeClusterServer(currentMode) {
|
134
|
+
this.behaviors.require(DishwasherModeServer, {
|
135
|
+
supportedModes: [
|
136
|
+
{ label: 'Light', mode: 1, modeTags: [{ value: DishwasherMode.ModeTag.Light }] },
|
137
|
+
{ label: 'Normal', mode: 2, modeTags: [{ value: DishwasherMode.ModeTag.Normal }] },
|
138
|
+
{ label: 'Heavy', mode: 3, modeTags: [{ value: DishwasherMode.ModeTag.Heavy }] },
|
139
|
+
],
|
140
|
+
currentMode,
|
141
|
+
});
|
142
|
+
return this;
|
143
|
+
}
|
144
|
+
createDefaultLaundryWasherModeClusterServer(currentMode) {
|
145
|
+
this.behaviors.require(LaundryWasherModeServer, {
|
146
|
+
supportedModes: [
|
147
|
+
{ label: 'Delicate', mode: 1, modeTags: [{ value: LaundryWasherMode.ModeTag.Delicate }] },
|
148
|
+
{ label: 'Normal', mode: 2, modeTags: [{ value: LaundryWasherMode.ModeTag.Normal }] },
|
149
|
+
{ label: 'Heavy', mode: 3, modeTags: [{ value: LaundryWasherMode.ModeTag.Heavy }] },
|
150
|
+
{ label: 'Whites', mode: 4, modeTags: [{ value: LaundryWasherMode.ModeTag.Whites }] },
|
151
|
+
],
|
152
|
+
currentMode,
|
153
|
+
});
|
154
|
+
return this;
|
155
|
+
}
|
156
|
+
createSpinLaundryWasherControlsClusterServer(spinSpeedCurrent, spinSpeeds) {
|
157
|
+
this.behaviors.require(LaundryWasherControlsServer.with(LaundryWasherControls.Feature.Spin), {
|
158
|
+
spinSpeeds: spinSpeeds ?? ['400', '800', '1200', '1600'],
|
159
|
+
spinSpeedCurrent,
|
160
|
+
});
|
161
|
+
return this;
|
162
|
+
}
|
163
|
+
createRinseLaundryWasherControlsClusterServer(numberOfRinses, supportedRinses) {
|
164
|
+
this.behaviors.require(LaundryWasherControlsServer.with(LaundryWasherControls.Feature.Rinse), {
|
165
|
+
supportedRinses: supportedRinses ?? [
|
166
|
+
LaundryWasherControls.NumberOfRinses.None,
|
167
|
+
LaundryWasherControls.NumberOfRinses.Normal,
|
168
|
+
LaundryWasherControls.NumberOfRinses.Extra,
|
169
|
+
LaundryWasherControls.NumberOfRinses.Max,
|
170
|
+
],
|
171
|
+
numberOfRinses,
|
172
|
+
});
|
173
|
+
return this;
|
174
|
+
}
|
175
|
+
createDefaultLaundryDryerControlsClusterServer(selectedDrynessLevel, supportedDrynessLevels) {
|
176
|
+
this.behaviors.require(LaundryDryerControlsServer, {
|
177
|
+
supportedDrynessLevels: supportedDrynessLevels ?? [
|
178
|
+
LaundryDryerControls.DrynessLevel.Low,
|
179
|
+
LaundryDryerControls.DrynessLevel.Normal,
|
180
|
+
LaundryDryerControls.DrynessLevel.Extra,
|
181
|
+
LaundryDryerControls.DrynessLevel.Max,
|
182
|
+
],
|
183
|
+
selectedDrynessLevel,
|
184
|
+
});
|
185
|
+
return this;
|
186
|
+
}
|
187
|
+
createDefaultDishwasherAlarmClusterServer() {
|
188
|
+
this.behaviors.require(DishwasherAlarmServer, {
|
189
|
+
mask: { inflowError: true, drainError: true, doorError: true, tempTooLow: true, tempTooHigh: true, waterLevelError: true },
|
190
|
+
state: { inflowError: false, drainError: false, doorError: false, tempTooLow: false, tempTooHigh: false, waterLevelError: false },
|
191
|
+
supported: { inflowError: true, drainError: true, doorError: true, tempTooLow: true, tempTooHigh: true, waterLevelError: true },
|
192
|
+
});
|
193
|
+
return this;
|
194
|
+
}
|
195
|
+
createDefaultOvenModeClusterServer(currentMode) {
|
196
|
+
this.behaviors.require(OvenModeServer, {
|
197
|
+
supportedModes: [
|
198
|
+
{ label: 'Bake', mode: 1, modeTags: [{ value: OvenMode.ModeTag.Bake }] },
|
199
|
+
{ label: 'Convection', mode: 2, modeTags: [{ value: OvenMode.ModeTag.Convection }] },
|
200
|
+
{ label: 'Grill', mode: 3, modeTags: [{ value: OvenMode.ModeTag.Grill }] },
|
201
|
+
{ label: 'Roast', mode: 4, modeTags: [{ value: OvenMode.ModeTag.Roast }] },
|
202
|
+
{ label: 'Clean', mode: 5, modeTags: [{ value: OvenMode.ModeTag.Clean }] },
|
203
|
+
{ label: 'Convection Bake', mode: 6, modeTags: [{ value: OvenMode.ModeTag.ConvectionBake }] },
|
204
|
+
{ label: 'Convection Roast', mode: 7, modeTags: [{ value: OvenMode.ModeTag.ConvectionRoast }] },
|
205
|
+
{ label: 'Warming', mode: 8, modeTags: [{ value: OvenMode.ModeTag.Warming }] },
|
206
|
+
{ label: 'Proofing', mode: 9, modeTags: [{ value: OvenMode.ModeTag.Proofing }] },
|
207
|
+
{ label: 'Steam', mode: 10, modeTags: [{ value: OvenMode.ModeTag.Steam }] },
|
208
|
+
],
|
209
|
+
currentMode,
|
210
|
+
});
|
211
|
+
return this;
|
212
|
+
}
|
213
|
+
createLevelTemperatureControlClusterServer(selectedTemperatureLevel = 1, supportedTemperatureLevels = ['Cold', 'Warm', 'Hot']) {
|
214
|
+
this.behaviors.require(MatterbridgeLevelTemperatureControlServer.with(TemperatureControl.Feature.TemperatureLevel), {
|
215
|
+
selectedTemperatureLevel,
|
216
|
+
supportedTemperatureLevels,
|
217
|
+
});
|
218
|
+
return this;
|
219
|
+
}
|
220
|
+
createNumberTemperatureControlClusterServer(temperatureSetpoint, minTemperature, maxTemperature, step = 1) {
|
221
|
+
this.behaviors.require(MatterbridgeNumberTemperatureControlServer.with(TemperatureControl.Feature.TemperatureNumber, TemperatureControl.Feature.TemperatureStep), {
|
222
|
+
temperatureSetpoint,
|
223
|
+
minTemperature,
|
224
|
+
maxTemperature,
|
225
|
+
step,
|
226
|
+
});
|
227
|
+
return this;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
class MatterbridgeOperationalStateServer extends OperationalStateBehavior {
|
231
|
+
initialize() {
|
232
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
233
|
+
device.log.info('MatterbridgeOperationalStateServer initialized: setting operational state to Stopped');
|
234
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
|
235
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
236
|
+
}
|
237
|
+
pause() {
|
238
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
239
|
+
device.log.info('MatterbridgeOperationalStateServer: pause called setting operational state to Paused');
|
240
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Paused;
|
241
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
242
|
+
return {
|
243
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
244
|
+
};
|
245
|
+
}
|
246
|
+
stop() {
|
247
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
248
|
+
device.log.info('MatterbridgeOperationalStateServer: stop called setting operational state to Stopped');
|
249
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
|
250
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
251
|
+
return {
|
252
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
253
|
+
};
|
254
|
+
}
|
255
|
+
start() {
|
256
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
257
|
+
device.log.info('MatterbridgeOperationalStateServer: start called setting operational state to Running');
|
258
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Running;
|
259
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
260
|
+
return {
|
261
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
262
|
+
};
|
263
|
+
}
|
264
|
+
resume() {
|
265
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
266
|
+
device.log.info('MatterbridgeOperationalStateServer: resume called setting operational state to Running');
|
267
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Running;
|
268
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
269
|
+
return {
|
270
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
271
|
+
};
|
272
|
+
}
|
273
|
+
}
|
274
|
+
class MatterbridgeLevelTemperatureControlServer extends TemperatureControlBehavior.with(TemperatureControl.Feature.TemperatureLevel) {
|
275
|
+
initialize() {
|
276
|
+
if (this.state.supportedTemperatureLevels.length >= 2) {
|
277
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
278
|
+
device.log.info('MatterbridgeLevelTemperatureControlServer initialized: setting selectedTemperatureLevel to 1');
|
279
|
+
this.state.selectedTemperatureLevel = 1;
|
280
|
+
}
|
281
|
+
}
|
282
|
+
setTemperature(request) {
|
283
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
284
|
+
if (request.targetTemperatureLevel !== undefined && request.targetTemperatureLevel >= 0 && request.targetTemperatureLevel < this.state.supportedTemperatureLevels.length) {
|
285
|
+
device.log.info(`MatterbridgeLevelTemperatureControlServer: setTemperature called setting selectedTemperatureLevel to ${request.targetTemperatureLevel}: ${this.state.supportedTemperatureLevels[request.targetTemperatureLevel]}`);
|
286
|
+
this.state.selectedTemperatureLevel = request.targetTemperatureLevel;
|
287
|
+
}
|
288
|
+
else {
|
289
|
+
device.log.error(`MatterbridgeLevelTemperatureControlServer: setTemperature called with invalid targetTemperatureLevel ${request.targetTemperatureLevel}`);
|
290
|
+
}
|
291
|
+
}
|
292
|
+
}
|
293
|
+
class MatterbridgeNumberTemperatureControlServer extends TemperatureControlBehavior.with(TemperatureControl.Feature.TemperatureNumber) {
|
294
|
+
initialize() {
|
295
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
296
|
+
device.log.info('MatterbridgeNumberTemperatureControlServer initialized');
|
297
|
+
}
|
298
|
+
setTemperature(request) {
|
299
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
300
|
+
if (request.targetTemperature !== undefined && request.targetTemperature >= this.state.minTemperature && request.targetTemperature <= this.state.maxTemperature) {
|
301
|
+
device.log.info(`MatterbridgeNumberTemperatureControlServer: setTemperature called setting temperatureSetpoint to ${request.targetTemperature}`);
|
302
|
+
this.state.temperatureSetpoint = request.targetTemperature;
|
303
|
+
}
|
304
|
+
else {
|
305
|
+
device.log.error(`MatterbridgeNumberTemperatureControlServer: setTemperature called with invalid targetTemperature ${request.targetTemperature}`);
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
export const OvenCavityOperationalStateBehavior = ClusterBehavior.withInterface().for(OvenCavityOperationalState.Cluster);
|
310
|
+
export class OvenCavityOperationalStateServer extends OvenCavityOperationalStateBehavior {
|
311
|
+
initialize() {
|
312
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
313
|
+
device.log.info('OvenCavityOperationalStateServer initialized: setting operational state to Stopped and operational error to No error');
|
314
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
|
315
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
316
|
+
}
|
317
|
+
stop() {
|
318
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
319
|
+
device.log.info('OvenCavityOperationalStateServer: stop called setting operational state to Stopped and operational error to No error');
|
320
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
|
321
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
322
|
+
return {
|
323
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
324
|
+
};
|
325
|
+
}
|
326
|
+
start() {
|
327
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
328
|
+
device.log.info('OvenCavityOperationalStateServer: start called setting operational state to Running and operational error to No error');
|
329
|
+
this.state.operationalState = OperationalState.OperationalStateEnum.Running;
|
330
|
+
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
331
|
+
return {
|
332
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
333
|
+
};
|
334
|
+
}
|
335
|
+
}
|
336
|
+
export const RefrigeratorAndTemperatureControlledCabinetModeBehavior = ClusterBehavior.withInterface().for(RefrigeratorAndTemperatureControlledCabinetMode.Cluster);
|
337
|
+
class RefrigeratorAndTemperatureControlledCabinetModeServer extends RefrigeratorAndTemperatureControlledCabinetModeBehavior {
|
338
|
+
initialize() {
|
339
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
340
|
+
device.log.info('MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer initialized: setting currentMode to 1');
|
341
|
+
this.state.currentMode = 1;
|
342
|
+
}
|
343
|
+
changeToMode(request) {
|
344
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
345
|
+
if (this.state.supportedModes.find((mode) => mode.mode === request.newMode)) {
|
346
|
+
device.log.info(`MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer: changeToMode called with mode ${request.newMode} = ${this.state.supportedModes[request.newMode].label}`);
|
347
|
+
this.state.currentMode = request.newMode;
|
348
|
+
return { status: Status.Success, statusText: 'Success' };
|
349
|
+
}
|
350
|
+
else {
|
351
|
+
device.log.info(`MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer: changeToMode called with invalid mode ${request.newMode}`);
|
352
|
+
return { status: Status.InvalidCommand, statusText: 'Invalid mode' };
|
353
|
+
}
|
354
|
+
}
|
355
|
+
}
|
356
|
+
export const OvenModeBehavior = ClusterBehavior.withInterface().for(OvenMode.Cluster);
|
357
|
+
class OvenModeServer extends OvenModeBehavior {
|
358
|
+
initialize() {
|
359
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
360
|
+
device.log.info('OvenModeServer initialized: setting currentMode to 3');
|
361
|
+
this.state.currentMode = 3;
|
362
|
+
}
|
363
|
+
changeToMode(request) {
|
364
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
365
|
+
if (this.state.supportedModes.find((mode) => mode.mode === request.newMode)) {
|
366
|
+
device.log.info(`OvenModeServer: changeToMode called with mode ${request.newMode} = ${this.state.supportedModes[request.newMode].label}`);
|
367
|
+
this.state.currentMode = request.newMode;
|
368
|
+
return { status: Status.Success, statusText: 'Success' };
|
369
|
+
}
|
370
|
+
else {
|
371
|
+
device.log.info(`OvenModeServer: changeToMode called with invalid mode ${request.newMode}`);
|
372
|
+
return { status: Status.InvalidCommand, statusText: 'Invalid mode' };
|
373
|
+
}
|
374
|
+
}
|
375
|
+
}
|
376
|
+
export const DishwasherModeBehavior = ClusterBehavior.withInterface().for(DishwasherMode.Cluster);
|
377
|
+
class DishwasherModeServer extends DishwasherModeBehavior {
|
378
|
+
initialize() {
|
379
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
380
|
+
device.log.info('DishwasherModeServer initialized: setting currentMode to 3');
|
381
|
+
this.state.currentMode = 2;
|
382
|
+
this.reactTo(this.agent.get(MatterbridgeOnOffServer).events.onOff$Changed, this.handleOnOffChange);
|
383
|
+
}
|
384
|
+
handleOnOffChange(onOff) {
|
385
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
386
|
+
if (onOff === false) {
|
387
|
+
device.log.info('***OnOffServer changed to OFF: setting Dead Front state to Manufacturer Specific');
|
388
|
+
this.state.currentMode = 2;
|
389
|
+
}
|
390
|
+
}
|
391
|
+
changeToMode(request) {
|
392
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
393
|
+
const supportedMode = this.state.supportedModes.find((supportedMode) => supportedMode.mode === request.newMode);
|
394
|
+
if (supportedMode) {
|
395
|
+
device.log.info(`DishwasherModeServer: changeToMode called with mode ${supportedMode.mode} = ${supportedMode.label}`);
|
396
|
+
this.state.currentMode = request.newMode;
|
397
|
+
return { status: Status.Success, statusText: 'Success' };
|
398
|
+
}
|
399
|
+
else {
|
400
|
+
device.log.error(`DishwasherModeServer: changeToMode called with invalid mode ${request.newMode}`);
|
401
|
+
return { status: Status.InvalidCommand, statusText: 'Invalid mode' };
|
402
|
+
}
|
403
|
+
}
|
404
|
+
}
|
405
|
+
export const LaundryWasherModeBehavior = ClusterBehavior.withInterface().for(LaundryWasherMode.Cluster);
|
406
|
+
class LaundryWasherModeServer extends LaundryWasherModeBehavior {
|
407
|
+
initialize() {
|
408
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
409
|
+
device.log.info('LaundryWasherModeServer initialized: setting currentMode to 3');
|
410
|
+
this.state.currentMode = 2;
|
411
|
+
this.reactTo(this.agent.get(MatterbridgeOnOffServer).events.onOff$Changed, this.handleOnOffChange);
|
412
|
+
}
|
413
|
+
handleOnOffChange(onOff) {
|
414
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
415
|
+
if (onOff === false) {
|
416
|
+
device.log.info('***OnOffServer changed to OFF: setting Dead Front state to Manufacturer Specific');
|
417
|
+
this.state.currentMode = 2;
|
418
|
+
}
|
419
|
+
}
|
420
|
+
changeToMode(request) {
|
421
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
422
|
+
const supportedMode = this.state.supportedModes.find((supportedMode) => supportedMode.mode === request.newMode);
|
423
|
+
if (supportedMode) {
|
424
|
+
device.log.info(`LaundryWasherModeServer: changeToMode called with mode ${supportedMode.mode} = ${supportedMode.label}`);
|
425
|
+
this.state.currentMode = request.newMode;
|
426
|
+
return { status: Status.Success, statusText: 'Success' };
|
427
|
+
}
|
428
|
+
else {
|
429
|
+
device.log.error(`LaundryWasherModeServer: changeToMode called with invalid mode ${request.newMode}`);
|
430
|
+
return { status: Status.InvalidCommand, statusText: 'Invalid mode' };
|
431
|
+
}
|
432
|
+
}
|
433
|
+
}
|
434
|
+
if (process.argv.includes('-testRobot')) {
|
435
|
+
const matterbridge = await Matterbridge.loadInstance(false);
|
436
|
+
matterbridge.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: "debug" });
|
437
|
+
matterbridge.environment.vars.set('log.level', MatterLogLevel.DEBUG);
|
438
|
+
matterbridge.environment.vars.set('log.format', MatterLogFormat.ANSI);
|
439
|
+
matterbridge.environment.vars.set('path.root', 'matterstorage');
|
440
|
+
matterbridge.environment.vars.set('runtime.signals', true);
|
441
|
+
matterbridge.environment.vars.set('runtime.exitcode', true);
|
442
|
+
matterbridge.environment.vars.set('mdns.networkInterface', 'Wi-Fi');
|
443
|
+
await matterbridge.startMatterStorage();
|
444
|
+
const deviceType = smokeCoAlarm;
|
445
|
+
const context = await matterbridge.createServerNodeContext('Jest', deviceType.name, DeviceTypeId(deviceType.code), VendorId(0xfff1), 'Matterbridge', 0x8000, 'Matterbridge device');
|
446
|
+
const server = await matterbridge.createServerNode(context);
|
447
|
+
const device = new Robot('Robot Vacuum', '99914248654');
|
448
|
+
await server.add(device);
|
449
|
+
logEndpoint(EndpointServer.forEndpoint(device));
|
450
|
+
await matterbridge.startServerNode(server);
|
451
|
+
logEndpoint(EndpointServer.forEndpoint(server));
|
452
|
+
}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import { ClusterBehavior } from 'matterbridge/matter';
|
2
|
+
import { Attribute, MutableCluster, OptionalAttribute, TlvEnum, TlvNullable, TlvUInt32, TlvFloat, FixedAttribute, BitFlag, ClusterType, ClusterRegistry, } from 'matterbridge/matter/types';
|
3
|
+
export var CarbonMonoxideConcentrationMeasurement;
|
4
|
+
(function (CarbonMonoxideConcentrationMeasurement) {
|
5
|
+
let Feature;
|
6
|
+
(function (Feature) {
|
7
|
+
Feature["NumericMeasurement"] = "NumericMeasurement";
|
8
|
+
Feature["LevelIndication"] = "LevelIndication";
|
9
|
+
Feature["MediumLevel"] = "MediumLevel";
|
10
|
+
Feature["CriticalLevel"] = "CriticalLevel";
|
11
|
+
Feature["PeakMeasurement"] = "PeakMeasurement";
|
12
|
+
Feature["AverageMeasurement"] = "AverageMeasurement";
|
13
|
+
})(Feature = CarbonMonoxideConcentrationMeasurement.Feature || (CarbonMonoxideConcentrationMeasurement.Feature = {}));
|
14
|
+
let MeasurementUnit;
|
15
|
+
(function (MeasurementUnit) {
|
16
|
+
MeasurementUnit[MeasurementUnit["Ppm"] = 0] = "Ppm";
|
17
|
+
MeasurementUnit[MeasurementUnit["Ppb"] = 1] = "Ppb";
|
18
|
+
MeasurementUnit[MeasurementUnit["Ppt"] = 2] = "Ppt";
|
19
|
+
MeasurementUnit[MeasurementUnit["Mgm3"] = 3] = "Mgm3";
|
20
|
+
MeasurementUnit[MeasurementUnit["Ugm3"] = 4] = "Ugm3";
|
21
|
+
MeasurementUnit[MeasurementUnit["Ngm3"] = 5] = "Ngm3";
|
22
|
+
MeasurementUnit[MeasurementUnit["Pm3"] = 6] = "Pm3";
|
23
|
+
MeasurementUnit[MeasurementUnit["Bqm3"] = 7] = "Bqm3";
|
24
|
+
})(MeasurementUnit = CarbonMonoxideConcentrationMeasurement.MeasurementUnit || (CarbonMonoxideConcentrationMeasurement.MeasurementUnit = {}));
|
25
|
+
let LevelValue;
|
26
|
+
(function (LevelValue) {
|
27
|
+
LevelValue[LevelValue["Unknown"] = 0] = "Unknown";
|
28
|
+
LevelValue[LevelValue["Low"] = 1] = "Low";
|
29
|
+
LevelValue[LevelValue["Medium"] = 2] = "Medium";
|
30
|
+
LevelValue[LevelValue["High"] = 3] = "High";
|
31
|
+
LevelValue[LevelValue["Critical"] = 4] = "Critical";
|
32
|
+
})(LevelValue = CarbonMonoxideConcentrationMeasurement.LevelValue || (CarbonMonoxideConcentrationMeasurement.LevelValue = {}));
|
33
|
+
let MeasurementMedium;
|
34
|
+
(function (MeasurementMedium) {
|
35
|
+
MeasurementMedium[MeasurementMedium["Air"] = 0] = "Air";
|
36
|
+
MeasurementMedium[MeasurementMedium["Water"] = 1] = "Water";
|
37
|
+
MeasurementMedium[MeasurementMedium["Soil"] = 2] = "Soil";
|
38
|
+
})(MeasurementMedium = CarbonMonoxideConcentrationMeasurement.MeasurementMedium || (CarbonMonoxideConcentrationMeasurement.MeasurementMedium = {}));
|
39
|
+
CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent = MutableCluster.Component({
|
40
|
+
attributes: {
|
41
|
+
measuredValue: Attribute(0x0, TlvNullable(TlvFloat), { default: null }),
|
42
|
+
minMeasuredValue: Attribute(0x1, TlvNullable(TlvFloat), { default: null }),
|
43
|
+
maxMeasuredValue: Attribute(0x2, TlvNullable(TlvFloat), { default: null }),
|
44
|
+
uncertainty: OptionalAttribute(0x7, TlvFloat),
|
45
|
+
measurementUnit: FixedAttribute(0x8, TlvEnum()),
|
46
|
+
},
|
47
|
+
});
|
48
|
+
CarbonMonoxideConcentrationMeasurement.PeakMeasurementComponent = MutableCluster.Component({
|
49
|
+
attributes: {
|
50
|
+
peakMeasuredValue: Attribute(0x3, TlvNullable(TlvFloat), { default: null }),
|
51
|
+
peakMeasuredValueWindow: Attribute(0x4, TlvUInt32.bound({ max: 604800 }), { default: 1 }),
|
52
|
+
},
|
53
|
+
});
|
54
|
+
CarbonMonoxideConcentrationMeasurement.AverageMeasurementComponent = MutableCluster.Component({
|
55
|
+
attributes: {
|
56
|
+
averageMeasuredValue: Attribute(0x5, TlvNullable(TlvFloat), { default: null }),
|
57
|
+
averageMeasuredValueWindow: Attribute(0x6, TlvUInt32.bound({ max: 604800 }), { default: 1 }),
|
58
|
+
},
|
59
|
+
});
|
60
|
+
CarbonMonoxideConcentrationMeasurement.LevelIndicationComponent = MutableCluster.Component({
|
61
|
+
attributes: {
|
62
|
+
levelValue: Attribute(0xa, TlvEnum(), { default: LevelValue.Unknown }),
|
63
|
+
},
|
64
|
+
});
|
65
|
+
CarbonMonoxideConcentrationMeasurement.Base = MutableCluster.Component({
|
66
|
+
id: 0x40c,
|
67
|
+
name: 'CarbonMonoxideConcentrationMeasurement',
|
68
|
+
revision: 3,
|
69
|
+
features: {
|
70
|
+
numericMeasurement: BitFlag(0),
|
71
|
+
levelIndication: BitFlag(1),
|
72
|
+
mediumLevel: BitFlag(2),
|
73
|
+
criticalLevel: BitFlag(3),
|
74
|
+
peakMeasurement: BitFlag(4),
|
75
|
+
averageMeasurement: BitFlag(5),
|
76
|
+
},
|
77
|
+
attributes: {
|
78
|
+
measurementMedium: FixedAttribute(0x9, TlvEnum()),
|
79
|
+
},
|
80
|
+
extensions: MutableCluster.Extensions({ flags: { numericMeasurement: true }, component: CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent }, { flags: { peakMeasurement: true }, component: CarbonMonoxideConcentrationMeasurement.PeakMeasurementComponent }, { flags: { averageMeasurement: true }, component: CarbonMonoxideConcentrationMeasurement.AverageMeasurementComponent }, { flags: { levelIndication: true }, component: CarbonMonoxideConcentrationMeasurement.LevelIndicationComponent }, { flags: { mediumLevel: true, levelIndication: false }, component: false }, { flags: { criticalLevel: true, levelIndication: false }, component: false }, { flags: { peakMeasurement: true, numericMeasurement: false }, component: false }, { flags: { averageMeasurement: true, numericMeasurement: false }, component: false }, { flags: { numericMeasurement: false, levelIndication: false }, component: false }),
|
81
|
+
});
|
82
|
+
CarbonMonoxideConcentrationMeasurement.ClusterInstance = MutableCluster.ExtensibleOnly(CarbonMonoxideConcentrationMeasurement.Base);
|
83
|
+
CarbonMonoxideConcentrationMeasurement.Cluster = CarbonMonoxideConcentrationMeasurement.ClusterInstance;
|
84
|
+
const MEA = { numericMeasurement: true };
|
85
|
+
const PEA = { peakMeasurement: true };
|
86
|
+
const AVG = { averageMeasurement: true };
|
87
|
+
const LEV = { levelIndication: true };
|
88
|
+
CarbonMonoxideConcentrationMeasurement.CompleteInstance = MutableCluster({
|
89
|
+
id: CarbonMonoxideConcentrationMeasurement.Base.id,
|
90
|
+
name: CarbonMonoxideConcentrationMeasurement.Base.name,
|
91
|
+
revision: CarbonMonoxideConcentrationMeasurement.Base.revision,
|
92
|
+
features: CarbonMonoxideConcentrationMeasurement.Base.features,
|
93
|
+
attributes: {
|
94
|
+
...CarbonMonoxideConcentrationMeasurement.Base.attributes,
|
95
|
+
measuredValue: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent.attributes.measuredValue, { mandatoryIf: [MEA] }),
|
96
|
+
minMeasuredValue: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent.attributes.minMeasuredValue, { mandatoryIf: [MEA] }),
|
97
|
+
maxMeasuredValue: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent.attributes.maxMeasuredValue, { mandatoryIf: [MEA] }),
|
98
|
+
peakMeasuredValue: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.PeakMeasurementComponent.attributes.peakMeasuredValue, { mandatoryIf: [PEA] }),
|
99
|
+
peakMeasuredValueWindow: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.PeakMeasurementComponent.attributes.peakMeasuredValueWindow, { mandatoryIf: [PEA] }),
|
100
|
+
averageMeasuredValue: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.AverageMeasurementComponent.attributes.averageMeasuredValue, { mandatoryIf: [AVG] }),
|
101
|
+
averageMeasuredValueWindow: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.AverageMeasurementComponent.attributes.averageMeasuredValueWindow, { mandatoryIf: [AVG] }),
|
102
|
+
uncertainty: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent.attributes.uncertainty, { optionalIf: [MEA] }),
|
103
|
+
measurementUnit: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.NumericMeasurementComponent.attributes.measurementUnit, { mandatoryIf: [MEA] }),
|
104
|
+
levelValue: MutableCluster.AsConditional(CarbonMonoxideConcentrationMeasurement.LevelIndicationComponent.attributes.levelValue, { mandatoryIf: [LEV] }),
|
105
|
+
},
|
106
|
+
});
|
107
|
+
CarbonMonoxideConcentrationMeasurement.Complete = CarbonMonoxideConcentrationMeasurement.CompleteInstance;
|
108
|
+
})(CarbonMonoxideConcentrationMeasurement || (CarbonMonoxideConcentrationMeasurement = {}));
|
109
|
+
export const CarbonMonoxideConcentrationMeasurementCluster = CarbonMonoxideConcentrationMeasurement.Cluster;
|
110
|
+
ClusterRegistry.register(ClusterType(CarbonMonoxideConcentrationMeasurement.Complete));
|
111
|
+
export const CarbonMonoxideConcentrationMeasurementBehavior = ClusterBehavior.for(ClusterType(CarbonMonoxideConcentrationMeasurement.Base));
|
112
|
+
export class CarbonMonoxideConcentrationMeasurementServer extends CarbonMonoxideConcentrationMeasurementBehavior.for(ClusterType(CarbonMonoxideConcentrationMeasurement.Base)) {
|
113
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { OperationalState } from 'matterbridge/matter/clusters';
|
2
|
+
import { Attribute, EventPriority, MutableCluster, OptionalAttribute, TlvArray, Event, TlvEnum, TlvNullable, TlvString, TlvUInt32, TlvUInt8, OptionalEvent, ClusterRegistry, TlvNoArguments, Command, } from 'matterbridge/matter/types';
|
3
|
+
export var OvenCavityOperationalState;
|
4
|
+
(function (OvenCavityOperationalState) {
|
5
|
+
OvenCavityOperationalState.ClusterInstance = MutableCluster({
|
6
|
+
id: 0x48,
|
7
|
+
name: 'OvenCavityOperationalState',
|
8
|
+
revision: 2,
|
9
|
+
attributes: {
|
10
|
+
phaseList: Attribute(0x0, TlvNullable(TlvArray(TlvString, { maxLength: 32 }))),
|
11
|
+
currentPhase: Attribute(0x1, TlvNullable(TlvUInt8)),
|
12
|
+
countdownTime: OptionalAttribute(0x2, TlvNullable(TlvUInt32.bound({ max: 259200 })), { default: null }),
|
13
|
+
operationalStateList: Attribute(0x3, TlvArray(OperationalState.TlvOperationalStateStruct), { default: [] }),
|
14
|
+
operationalState: Attribute(0x4, TlvEnum()),
|
15
|
+
operationalError: Attribute(0x5, OperationalState.TlvErrorStateStruct),
|
16
|
+
},
|
17
|
+
commands: {
|
18
|
+
stop: Command(0x1, TlvNoArguments, 0x4, OperationalState.TlvOperationalCommandResponse),
|
19
|
+
start: Command(0x2, TlvNoArguments, 0x4, OperationalState.TlvOperationalCommandResponse),
|
20
|
+
},
|
21
|
+
events: {
|
22
|
+
operationalError: Event(0x0, EventPriority.Critical, OperationalState.TlvOperationalErrorEvent),
|
23
|
+
operationCompletion: OptionalEvent(0x1, EventPriority.Info, OperationalState.TlvOperationCompletionEvent),
|
24
|
+
},
|
25
|
+
});
|
26
|
+
OvenCavityOperationalState.Cluster = OvenCavityOperationalState.ClusterInstance;
|
27
|
+
OvenCavityOperationalState.Complete = OvenCavityOperationalState.Cluster;
|
28
|
+
})(OvenCavityOperationalState || (OvenCavityOperationalState = {}));
|
29
|
+
export const OvenCavityOperationalStateCluster = OvenCavityOperationalState.Cluster;
|
30
|
+
ClusterRegistry.register(OvenCavityOperationalState.Complete);
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import { OperationalState as OperationalStateNamespace } from 'matterbridge/matter/clusters';
|
2
|
+
import { Attribute, ClusterRegistry, Event, EventPriority, MutableCluster, OptionalAttribute, OptionalCommand, OptionalEvent, TlvArray, TlvEnum, TlvField, TlvNoArguments, TlvNullable, TlvObject, TlvOptionalField, TlvString, TlvUInt32, TlvUInt8, } from 'matterbridge/matter/types';
|
3
|
+
export var RvcOperationalState;
|
4
|
+
(function (RvcOperationalState) {
|
5
|
+
let OperationalState;
|
6
|
+
(function (OperationalState) {
|
7
|
+
OperationalState[OperationalState["Stopped"] = 0] = "Stopped";
|
8
|
+
OperationalState[OperationalState["Running"] = 1] = "Running";
|
9
|
+
OperationalState[OperationalState["Paused"] = 2] = "Paused";
|
10
|
+
OperationalState[OperationalState["Error"] = 3] = "Error";
|
11
|
+
OperationalState[OperationalState["SeekingCharger"] = 64] = "SeekingCharger";
|
12
|
+
OperationalState[OperationalState["Charging"] = 65] = "Charging";
|
13
|
+
OperationalState[OperationalState["Docked"] = 66] = "Docked";
|
14
|
+
})(OperationalState = RvcOperationalState.OperationalState || (RvcOperationalState.OperationalState = {}));
|
15
|
+
RvcOperationalState.TlvOperationalStateStruct = TlvObject({
|
16
|
+
operationalStateId: TlvField(0, TlvEnum()),
|
17
|
+
operationalStateLabel: TlvOptionalField(1, TlvString.bound({ maxLength: 64 })),
|
18
|
+
});
|
19
|
+
let ErrorState;
|
20
|
+
(function (ErrorState) {
|
21
|
+
ErrorState[ErrorState["NoError"] = 0] = "NoError";
|
22
|
+
ErrorState[ErrorState["UnableToStartOrResume"] = 1] = "UnableToStartOrResume";
|
23
|
+
ErrorState[ErrorState["UnableToCompleteOperation"] = 2] = "UnableToCompleteOperation";
|
24
|
+
ErrorState[ErrorState["CommandInvalidInState"] = 3] = "CommandInvalidInState";
|
25
|
+
ErrorState[ErrorState["FailedToFindChargingDock"] = 64] = "FailedToFindChargingDock";
|
26
|
+
ErrorState[ErrorState["Stuck"] = 65] = "Stuck";
|
27
|
+
ErrorState[ErrorState["DustBinMissing"] = 66] = "DustBinMissing";
|
28
|
+
ErrorState[ErrorState["DustBinFull"] = 67] = "DustBinFull";
|
29
|
+
ErrorState[ErrorState["WaterTankEmpty"] = 68] = "WaterTankEmpty";
|
30
|
+
ErrorState[ErrorState["WaterTankMissing"] = 69] = "WaterTankMissing";
|
31
|
+
ErrorState[ErrorState["WaterTankLidOpen"] = 70] = "WaterTankLidOpen";
|
32
|
+
ErrorState[ErrorState["MopCleaningPadMissing"] = 71] = "MopCleaningPadMissing";
|
33
|
+
})(ErrorState = RvcOperationalState.ErrorState || (RvcOperationalState.ErrorState = {}));
|
34
|
+
RvcOperationalState.TlvErrorStateStruct = TlvObject({
|
35
|
+
errorStateId: TlvField(0, TlvEnum()),
|
36
|
+
errorStateLabel: TlvOptionalField(1, TlvString.bound({ maxLength: 64 })),
|
37
|
+
errorStateDetails: TlvOptionalField(2, TlvString.bound({ maxLength: 64 })),
|
38
|
+
});
|
39
|
+
RvcOperationalState.TlvOperationalCommandResponse = TlvObject({
|
40
|
+
commandResponseState: TlvField(0, RvcOperationalState.TlvErrorStateStruct),
|
41
|
+
});
|
42
|
+
RvcOperationalState.TlvOperationalErrorEvent = TlvObject({ errorState: TlvField(0, RvcOperationalState.TlvErrorStateStruct) });
|
43
|
+
RvcOperationalState.ClusterInstance = MutableCluster({
|
44
|
+
id: 0x61,
|
45
|
+
name: 'RvcOperationalState',
|
46
|
+
revision: 2,
|
47
|
+
attributes: {
|
48
|
+
phaseList: Attribute(0x0, TlvNullable(TlvArray(TlvString, { maxLength: 32 }))),
|
49
|
+
currentPhase: Attribute(0x1, TlvNullable(TlvUInt8)),
|
50
|
+
countdownTime: OptionalAttribute(0x2, TlvNullable(TlvUInt32.bound({ max: 259200 })), { default: null }),
|
51
|
+
operationalStateList: Attribute(0x3, TlvArray(RvcOperationalState.TlvOperationalStateStruct), { default: [] }),
|
52
|
+
operationalState: Attribute(0x4, TlvEnum()),
|
53
|
+
operationalError: Attribute(0x5, RvcOperationalState.TlvErrorStateStruct),
|
54
|
+
},
|
55
|
+
commands: {
|
56
|
+
pause: OptionalCommand(0x0, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
57
|
+
stop: OptionalCommand(0x1, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
58
|
+
start: OptionalCommand(0x2, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
59
|
+
resume: OptionalCommand(0x3, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
60
|
+
goHome: OptionalCommand(0x80, TlvNoArguments, 0x4, RvcOperationalState.TlvOperationalCommandResponse),
|
61
|
+
},
|
62
|
+
events: {
|
63
|
+
operationalError: Event(0x0, EventPriority.Critical, RvcOperationalState.TlvOperationalErrorEvent),
|
64
|
+
operationCompletion: OptionalEvent(0x1, EventPriority.Info, OperationalStateNamespace.TlvOperationCompletionEvent),
|
65
|
+
},
|
66
|
+
});
|
67
|
+
RvcOperationalState.Cluster = RvcOperationalState.ClusterInstance;
|
68
|
+
RvcOperationalState.Complete = RvcOperationalState.Cluster;
|
69
|
+
})(RvcOperationalState || (RvcOperationalState = {}));
|
70
|
+
export const RvcOperationalStateCluster = RvcOperationalState.Cluster;
|
71
|
+
ClusterRegistry.register(RvcOperationalState.Complete);
|
package/dist/platform.js
CHANGED
@@ -2,6 +2,8 @@ import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airConditioner, airQ
|
|
2
2
|
import { isValidBoolean, isValidNumber } from 'matterbridge/utils';
|
3
3
|
import { LocationTag } from 'matterbridge/matter';
|
4
4
|
import { PowerSource, BooleanState, OnOff, LevelControl, AirQuality, CarbonDioxideConcentrationMeasurement, CarbonMonoxideConcentrationMeasurement, FlowMeasurement, ColorControl, DoorLock, FanControl, FormaldehydeConcentrationMeasurement, NitrogenDioxideConcentrationMeasurement, OzoneConcentrationMeasurement, Pm10ConcentrationMeasurement, Pm1ConcentrationMeasurement, Pm25ConcentrationMeasurement, RadonConcentrationMeasurement, RelativeHumidityMeasurement, RelativeHumidityMeasurementCluster, SmokeCoAlarm, TemperatureMeasurement, Thermostat, ThermostatCluster, TotalVolatileOrganicCompoundsConcentrationMeasurement, WindowCovering, } from 'matterbridge/matter/clusters';
|
5
|
+
import { Appliances } from './appliances.js';
|
6
|
+
import { Robot } from './robot.js';
|
5
7
|
export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
|
6
8
|
switch;
|
7
9
|
mountedOnOffSwitch;
|
@@ -635,7 +637,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
635
637
|
this.pump = new MatterbridgeEndpoint([pumpDevice, bridgedNode, powerSource], { uniqueStorageKey: 'Pump' }, this.config.debug)
|
636
638
|
.createDefaultBridgedDeviceBasicInformationClusterServer('Pump', '0x96382864PUMP', 0xfff1, 'Matterbridge', 'Matterbridge Pump', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
|
637
639
|
.createDefaultIdentifyClusterServer()
|
638
|
-
.
|
640
|
+
.createOnOffClusterServer()
|
641
|
+
.createLevelControlClusterServer()
|
639
642
|
.createDefaultPumpConfigurationAndControlClusterServer()
|
640
643
|
.createDefaultPowerSourceWiredClusterServer();
|
641
644
|
this.setSelectDevice(this.pump.serialNumber ?? '', this.pump.deviceName ?? '', undefined, 'hub');
|
@@ -850,6 +853,42 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
850
853
|
else {
|
851
854
|
this.latchingSwitch = undefined;
|
852
855
|
}
|
856
|
+
const robot = new Robot('Robot Vacuum', '1238777820');
|
857
|
+
this.setSelectDevice(robot.serialNumber ?? '', robot.deviceName ?? '', undefined, 'hub');
|
858
|
+
if (this.validateDevice(robot.deviceName ?? '')) {
|
859
|
+
await this.registerDevice(robot);
|
860
|
+
this.bridgedDevices.set(robot.deviceName ?? '', robot);
|
861
|
+
}
|
862
|
+
const laundryWasher = new Appliances(Appliances.laundryWasher, 'Laundry Washer', '1234567890');
|
863
|
+
this.setSelectDevice(laundryWasher.serialNumber ?? '', laundryWasher.deviceName ?? '', undefined, 'hub');
|
864
|
+
if (this.validateDevice(laundryWasher.deviceName ?? '')) {
|
865
|
+
await this.registerDevice(laundryWasher);
|
866
|
+
this.bridgedDevices.set(laundryWasher.deviceName ?? '', laundryWasher);
|
867
|
+
}
|
868
|
+
const laundryDryer = new Appliances(Appliances.laundryDryer, 'Laundry Dryer', '1235227890');
|
869
|
+
this.setSelectDevice(laundryDryer.serialNumber ?? '', laundryDryer.deviceName ?? '', undefined, 'hub');
|
870
|
+
if (this.validateDevice(laundryDryer.deviceName ?? '')) {
|
871
|
+
await this.registerDevice(laundryDryer);
|
872
|
+
this.bridgedDevices.set(laundryDryer.deviceName ?? '', laundryDryer);
|
873
|
+
}
|
874
|
+
const dishwasher = new Appliances(Appliances.dishwasher, 'Dishwasher', '0987654321');
|
875
|
+
this.setSelectDevice(dishwasher.serialNumber ?? '', dishwasher.deviceName ?? '', undefined, 'hub');
|
876
|
+
if (this.validateDevice(dishwasher.deviceName ?? '')) {
|
877
|
+
await this.registerDevice(dishwasher);
|
878
|
+
this.bridgedDevices.set(dishwasher.deviceName ?? '', dishwasher);
|
879
|
+
}
|
880
|
+
const temperatureControlledCabinetCooler = new Appliances(Appliances.temperatureControlledCabinetCooler, 'Temperature Controlled Cabinet Cooler', '0986594321');
|
881
|
+
this.setSelectDevice(temperatureControlledCabinetCooler.serialNumber ?? '', temperatureControlledCabinetCooler.deviceName ?? '', undefined, 'hub');
|
882
|
+
if (this.validateDevice(temperatureControlledCabinetCooler.deviceName ?? '')) {
|
883
|
+
await this.registerDevice(temperatureControlledCabinetCooler);
|
884
|
+
this.bridgedDevices.set(temperatureControlledCabinetCooler.deviceName ?? '', temperatureControlledCabinetCooler);
|
885
|
+
}
|
886
|
+
const temperatureControlledCabinetHeater = new Appliances(Appliances.temperatureControlledCabinetHeater, 'Temperature Controlled Cabinet Heater', '0986554421');
|
887
|
+
this.setSelectDevice(temperatureControlledCabinetHeater.serialNumber ?? '', temperatureControlledCabinetHeater.deviceName ?? '', undefined, 'hub');
|
888
|
+
if (this.validateDevice(temperatureControlledCabinetHeater.deviceName ?? '')) {
|
889
|
+
await this.registerDevice(temperatureControlledCabinetHeater);
|
890
|
+
this.bridgedDevices.set(temperatureControlledCabinetHeater.deviceName ?? '', temperatureControlledCabinetHeater);
|
891
|
+
}
|
853
892
|
}
|
854
893
|
async onConfigure() {
|
855
894
|
await super.onConfigure();
|
@@ -1153,6 +1192,6 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
1153
1192
|
await super.onShutdown(reason);
|
1154
1193
|
this.log.info('onShutdown called with reason:', reason ?? 'none');
|
1155
1194
|
if (this.config.unregisterOnShutdown === true)
|
1156
|
-
await this.unregisterAllDevices();
|
1195
|
+
await this.unregisterAllDevices(250);
|
1157
1196
|
}
|
1158
1197
|
}
|
package/dist/robot.js
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
import { MatterbridgeServer, MatterbridgeEndpoint, roboticVacuumCleaner } from 'matterbridge';
|
2
|
+
import { RvcOperationalState } from './implementations/roboticVacuumCleanerClusters.js';
|
3
|
+
import { ClusterBehavior } from 'matterbridge/matter';
|
4
|
+
import { Status } from 'matterbridge/matter/types';
|
5
|
+
import { OperationalState, PowerSource, RvcRunMode, RvcCleanMode, ServiceArea } from 'matterbridge/matter/clusters';
|
6
|
+
import { OnOffServer, ServiceAreaBehavior } from 'matterbridge/matter/behaviors';
|
7
|
+
export class Robot extends MatterbridgeEndpoint {
|
8
|
+
constructor(name, serial) {
|
9
|
+
super(roboticVacuumCleaner, { uniqueStorageKey: `${name}-${serial}` }, true);
|
10
|
+
this.createDefaultIdentifyClusterServer()
|
11
|
+
.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Robot Vacuum Cleaner')
|
12
|
+
.createDefaultOnOffClusterServer()
|
13
|
+
.createDefaultRvcRunModeClusterServer()
|
14
|
+
.createDefaultRvcOperationalStateClusterServer()
|
15
|
+
.createDefaultRvcCleanModeClusterServer()
|
16
|
+
.createDefaultServiceAreaClusterServer()
|
17
|
+
.createDefaultPowerSourceRechargeableBatteryClusterServer(80, PowerSource.BatChargeLevel.Ok, 5900);
|
18
|
+
}
|
19
|
+
createDefaultRvcRunModeClusterServer() {
|
20
|
+
this.behaviors.require(MatterbridgeRvcRunModeServer, {
|
21
|
+
supportedModes: [
|
22
|
+
{ label: 'Idle', mode: 1, modeTags: [{ value: RvcRunMode.ModeTag.Idle }] },
|
23
|
+
{ label: 'Cleaning', mode: 2, modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }] },
|
24
|
+
{ label: 'Mapping', mode: 3, modeTags: [{ value: RvcRunMode.ModeTag.Mapping }] },
|
25
|
+
{ label: 'SpotCleaning', mode: 4, modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }, { value: RvcRunMode.ModeTag.Max }] },
|
26
|
+
],
|
27
|
+
currentMode: 1,
|
28
|
+
});
|
29
|
+
return this;
|
30
|
+
}
|
31
|
+
createDefaultRvcCleanModeClusterServer() {
|
32
|
+
this.behaviors.require(MatterbridgeRvcCleanModeServer, {
|
33
|
+
supportedModes: [
|
34
|
+
{ label: 'Vacuum', mode: 1, modeTags: [{ value: RvcCleanMode.ModeTag.Vacuum }] },
|
35
|
+
{ label: 'Mop', mode: 2, modeTags: [{ value: RvcCleanMode.ModeTag.Mop }] },
|
36
|
+
{ label: 'Clean', mode: 3, modeTags: [{ value: RvcCleanMode.ModeTag.DeepClean }] },
|
37
|
+
],
|
38
|
+
currentMode: 1,
|
39
|
+
});
|
40
|
+
return this;
|
41
|
+
}
|
42
|
+
createDefaultServiceAreaClusterServer(supportedAreas, selectedAreas) {
|
43
|
+
this.behaviors.require(MatterbridgeServiceAreaServer, {
|
44
|
+
supportedAreas: supportedAreas ?? [
|
45
|
+
{
|
46
|
+
areaId: 1,
|
47
|
+
mapId: null,
|
48
|
+
areaInfo: { locationInfo: { locationName: 'Living', floorNumber: null, areaType: null }, landmarkInfo: null },
|
49
|
+
},
|
50
|
+
{
|
51
|
+
areaId: 2,
|
52
|
+
mapId: null,
|
53
|
+
areaInfo: { locationInfo: { locationName: 'Kitchen', floorNumber: null, areaType: null }, landmarkInfo: null },
|
54
|
+
},
|
55
|
+
{
|
56
|
+
areaId: 3,
|
57
|
+
mapId: null,
|
58
|
+
areaInfo: { locationInfo: { locationName: 'Bedroom', floorNumber: null, areaType: null }, landmarkInfo: null },
|
59
|
+
},
|
60
|
+
{
|
61
|
+
areaId: 4,
|
62
|
+
mapId: null,
|
63
|
+
areaInfo: { locationInfo: { locationName: 'Bathroom', floorNumber: null, areaType: null }, landmarkInfo: null },
|
64
|
+
},
|
65
|
+
],
|
66
|
+
selectedAreas: selectedAreas ?? [],
|
67
|
+
currentArea: 1,
|
68
|
+
estimatedEndTime: null,
|
69
|
+
});
|
70
|
+
return this;
|
71
|
+
}
|
72
|
+
createDefaultRvcOperationalStateClusterServer() {
|
73
|
+
this.behaviors.require(MatterbridgeRvcOperationalStateServer, {
|
74
|
+
phaseList: [],
|
75
|
+
currentPhase: null,
|
76
|
+
operationalStateList: [
|
77
|
+
{ operationalStateId: RvcOperationalState.OperationalState.Stopped, operationalStateLabel: 'Stopped' },
|
78
|
+
{ operationalStateId: RvcOperationalState.OperationalState.Running, operationalStateLabel: 'Running' },
|
79
|
+
{ operationalStateId: RvcOperationalState.OperationalState.Paused, operationalStateLabel: 'Paused' },
|
80
|
+
{ operationalStateId: RvcOperationalState.OperationalState.Error, operationalStateLabel: 'Error' },
|
81
|
+
{ operationalStateId: RvcOperationalState.OperationalState.SeekingCharger, operationalStateLabel: 'SeekingCharger' },
|
82
|
+
{ operationalStateId: RvcOperationalState.OperationalState.Charging, operationalStateLabel: 'Charging' },
|
83
|
+
{ operationalStateId: RvcOperationalState.OperationalState.Docked, operationalStateLabel: 'Docked' },
|
84
|
+
],
|
85
|
+
operationalState: RvcOperationalState.OperationalState.Docked,
|
86
|
+
operationalError: { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' },
|
87
|
+
});
|
88
|
+
return this;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
export class MatterbridgeServiceAreaServer extends ServiceAreaBehavior {
|
92
|
+
initialize() {
|
93
|
+
}
|
94
|
+
selectAreas({ newAreas }) {
|
95
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
96
|
+
for (const area of newAreas) {
|
97
|
+
const supportedArea = this.state.supportedAreas.find((supportedArea) => supportedArea.areaId === area);
|
98
|
+
if (!supportedArea) {
|
99
|
+
device.log.error('MatterbridgeServiceAreaServer selectAreas called with unsupported area:', area);
|
100
|
+
return { status: ServiceArea.SelectAreasStatus.UnsupportedArea, statusText: 'Unsupported areas' };
|
101
|
+
}
|
102
|
+
}
|
103
|
+
this.state.selectedAreas = newAreas;
|
104
|
+
return { status: ServiceArea.SelectAreasStatus.Success, statusText: 'Succesfully selected new areas' };
|
105
|
+
}
|
106
|
+
}
|
107
|
+
export const RvcRunModeBehavior = ClusterBehavior.withInterface().for(RvcRunMode.Cluster);
|
108
|
+
export class MatterbridgeRvcRunModeServer extends RvcRunModeBehavior {
|
109
|
+
initialize() {
|
110
|
+
this.state.currentMode = 1;
|
111
|
+
}
|
112
|
+
changeToMode({ newMode }) {
|
113
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
114
|
+
const supported = this.state.supportedModes.find((mode) => mode.mode === newMode);
|
115
|
+
if (!supported) {
|
116
|
+
device.log.error('MatterbridgeRvcRunModeServer changeToMode called with unsupported newMode:', newMode);
|
117
|
+
return { status: Status.InvalidCommand, statusText: 'Invalid command' };
|
118
|
+
}
|
119
|
+
device.changeToMode({ newMode });
|
120
|
+
this.state.currentMode = newMode;
|
121
|
+
if (supported.modeTags.find((tag) => tag.value === RvcRunMode.ModeTag.Cleaning)) {
|
122
|
+
device.log.info('***MatterbridgeRvcRunModeServer changeToMode called with newMode Cleaning => Running');
|
123
|
+
this.agent.get(MatterbridgeRvcOperationalStateServer).state.operationalState = RvcOperationalState.OperationalState.Running;
|
124
|
+
return { status: Status.Success, statusText: 'Running' };
|
125
|
+
}
|
126
|
+
else if (supported.modeTags.find((tag) => tag.value === RvcRunMode.ModeTag.Idle)) {
|
127
|
+
device.log.info('***MatterbridgeRvcRunModeServer changeToMode called with newMode Idle => Docked');
|
128
|
+
this.agent.get(MatterbridgeRvcOperationalStateServer).state.operationalState = RvcOperationalState.OperationalState.Docked;
|
129
|
+
return { status: Status.Success, statusText: 'Docked' };
|
130
|
+
}
|
131
|
+
device.log.info(`***MatterbridgeRvcRunModeServer changeToMode called with newMode ${newMode} => ${supported.label}`);
|
132
|
+
this.agent.get(MatterbridgeRvcOperationalStateServer).state.operationalState = RvcOperationalState.OperationalState.Running;
|
133
|
+
return { status: Status.Success, statusText: 'Success' };
|
134
|
+
}
|
135
|
+
}
|
136
|
+
export const RvcCleanModeBehavior = ClusterBehavior.withInterface().for(RvcCleanMode.Cluster);
|
137
|
+
export class MatterbridgeRvcCleanModeServer extends RvcCleanModeBehavior {
|
138
|
+
initialize() {
|
139
|
+
this.state.currentMode = 1;
|
140
|
+
}
|
141
|
+
changeToMode({ newMode }) {
|
142
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
143
|
+
const supported = this.state.supportedModes.find((mode) => mode.mode === newMode);
|
144
|
+
if (!supported) {
|
145
|
+
device.log.error('***MatterbridgeRvcCleanModeServer changeToMode called with unsupported newMode:', newMode);
|
146
|
+
return { status: Status.InvalidCommand, statusText: 'Invalid command' };
|
147
|
+
}
|
148
|
+
device.changeToMode({ newMode });
|
149
|
+
this.state.currentMode = newMode;
|
150
|
+
device.log.info(`***MatterbridgeRvcCleanModeServer changeToMode called with newMode ${newMode} => ${supported.label}`);
|
151
|
+
return { status: Status.Success, statusText: 'Success' };
|
152
|
+
}
|
153
|
+
}
|
154
|
+
export const RvcOperationalStateBehavior = ClusterBehavior.withInterface().for(RvcOperationalState.Cluster);
|
155
|
+
export class MatterbridgeRvcOperationalStateServer extends RvcOperationalStateBehavior {
|
156
|
+
initialize() {
|
157
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
158
|
+
device.log.info('***MatterbridgeRvcOperationalStateServer initialized: setting operational state to Docked');
|
159
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
160
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
161
|
+
this.reactTo(this.agent.get(OnOffServer).events.onOff$Changed, this.handleOnOffChange);
|
162
|
+
}
|
163
|
+
handleOnOffChange(onOff) {
|
164
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
165
|
+
if (onOff) {
|
166
|
+
device.log.info('***OnOffServer changed to ON: setting operational state to Running');
|
167
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 2;
|
168
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Running;
|
169
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
170
|
+
}
|
171
|
+
else {
|
172
|
+
device.log.info('***OnOffServer changed to OFF: setting operational state to Docked');
|
173
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
174
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
175
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
176
|
+
}
|
177
|
+
}
|
178
|
+
pause() {
|
179
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
180
|
+
device.log.info('MatterbridgeRvcOperationalStateServer: pause called setting operational state to Paused and currentMode to Idle');
|
181
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
182
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Paused;
|
183
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
184
|
+
return {
|
185
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
186
|
+
};
|
187
|
+
}
|
188
|
+
resume() {
|
189
|
+
const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
|
190
|
+
device.log.info('MatterbridgeRvcOperationalStateServer: resume called setting operational state to Running and currentMode to Cleaning');
|
191
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 2;
|
192
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Running;
|
193
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
194
|
+
return {
|
195
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
196
|
+
};
|
197
|
+
}
|
198
|
+
goHome() {
|
199
|
+
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
200
|
+
device.log.info('MatterbridgeRvcOperationalStateServer: goHome called setting operational state to Docked and currentMode to Idle');
|
201
|
+
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
202
|
+
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
203
|
+
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
204
|
+
return {
|
205
|
+
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
206
|
+
};
|
207
|
+
}
|
208
|
+
}
|
package/npm-shrinkwrap.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "matterbridge-example-dynamic-platform",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.2.0-edge.5",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "matterbridge-example-dynamic-platform",
|
9
|
-
"version": "1.
|
9
|
+
"version": "1.2.0-edge.5",
|
10
10
|
"license": "MIT",
|
11
11
|
"dependencies": {
|
12
12
|
"node-ansi-logger": "3.0.1",
|