matterbridge-example-dynamic-platform 1.2.0 → 1.2.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 +30 -1
- package/README.md +2 -1
- package/dist/appliances.js +3 -62
- package/dist/platform.js +32 -28
- package/matterbridge-example-dynamic-platform.schema.json +1 -6
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/robot.js +0 -210
package/CHANGELOG.md
CHANGED
@@ -8,11 +8,40 @@ 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.2] - 2025-05-19
|
12
|
+
|
13
|
+
### Changed
|
14
|
+
|
15
|
+
- [package]: Added waterHeater device type (not supported by Alexa and Apple Home)
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- [package]: Changed the RVC from local implementation to the new RoboticVacuumCleaner class from matterbridge.
|
20
|
+
- [package]: Require matterbridge 3.0.3.
|
21
|
+
- [package]: Updated package.
|
22
|
+
- [package]: Updated dependencies.
|
23
|
+
|
24
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
25
|
+
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
26
|
+
</a>
|
27
|
+
|
28
|
+
## [1.2.1] - 2025-05-15
|
29
|
+
|
30
|
+
### Changed
|
31
|
+
|
32
|
+
- [package]: Require matterbridge 3.0.1.
|
33
|
+
- [package]: Updated package.
|
34
|
+
- [package]: Updated dependencies.
|
35
|
+
|
36
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
37
|
+
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
38
|
+
</a>
|
39
|
+
|
11
40
|
## [1.2.0] - 2025-04-30
|
12
41
|
|
13
42
|
### Added
|
14
43
|
|
15
|
-
- [platform]: Added Robot Vacuum Cleaner device (supported by SmartThings, Alexa, Home Assistant and partially by Apple Home). Read carefully the readme please.
|
44
|
+
- [platform]: Added Robot Vacuum Cleaner device (supported by SmartThings, Alexa, Home Assistant and partially by Apple Home). Read carefully the readme please and also https://github.com/Luligu/matterbridge/discussions/264.
|
16
45
|
- [platform]: Added OnOff Mounted Switch device (supported by SmartThings, Alexa, Home Assistant).
|
17
46
|
- [platform]: Added Dimmer Mounted Switch device (supported by SmartThings, Alexa, Home Assistant).
|
18
47
|
- [platform]: Added Laundry Washer device (supported by SmartThings, Alexa and Home Assistant).
|
package/README.md
CHANGED
@@ -43,7 +43,7 @@ It exposes 38 devices:
|
|
43
43
|
- an airPurifier device with temperature and humidity sensor (supported by Apple Home)
|
44
44
|
- a pumpDevice device
|
45
45
|
- a waterValve device
|
46
|
-
- an airQuality device with all concentration measurements clusters (supported by Apple Home
|
46
|
+
- an airQuality device with all concentration measurements clusters (supported by Apple Home with the concentration measurements from version 18.5)
|
47
47
|
- a momentary switch
|
48
48
|
- a latching switch
|
49
49
|
- a Robot Vacuum Cleaner device (supported by SmartThings, Alexa, Home Assistant and partially by Apple Home). Read also https://github.com/Luligu/matterbridge/discussions/264.
|
@@ -57,6 +57,7 @@ It exposes 38 devices:
|
|
57
57
|
- a microwave Oven device (supported by SmartThings, Alexa and Home Assistant)
|
58
58
|
- an extractor Hood device (supported by SmartThings, Alexa and Home Assistant)
|
59
59
|
- a cooktop device (supported by SmartThings, Alexa and Home Assistant)
|
60
|
+
- a water heater device (supported by SmartThings and Home Assistant)
|
60
61
|
|
61
62
|
All these devices continuously change state and position. The plugin also shows how to use all the command handlers (you can control all the devices), how to subscribe to attributes and how to trigger events.
|
62
63
|
|
package/dist/appliances.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
import { MatterbridgeEndpoint, MatterbridgeServer, MatterbridgeOnOffServer,
|
2
|
-
import { ClusterBehavior } from 'matterbridge/matter';
|
1
|
+
import { MatterbridgeEndpoint, MatterbridgeServer, MatterbridgeOnOffServer, laundryWasher, laundryDryer, dishwasher, refrigerator, temperatureControlledCabinetCooler, oven, temperatureControlledCabinetHeater, microwaveOven, extractorHood, cooktop, cookSurface, powerSource, } from 'matterbridge';
|
2
|
+
import { ClusterBehavior, PositionTag, RefrigeratorTag } from 'matterbridge/matter';
|
3
3
|
import { OperationalState, TemperatureControl, DishwasherMode, LaundryWasherControls, LaundryWasherMode, LaundryDryerControls, OvenMode, ModeBase, RefrigeratorAndTemperatureControlledCabinetMode, MicrowaveOvenMode, MicrowaveOvenControl, OvenCavityOperationalState, } from 'matterbridge/matter/clusters';
|
4
|
-
import { DishwasherAlarmServer, LaundryDryerControlsServer, LaundryWasherControlsServer, MicrowaveOvenControlBehavior, MicrowaveOvenModeServer,
|
4
|
+
import { DishwasherAlarmServer, LaundryDryerControlsServer, LaundryWasherControlsServer, MicrowaveOvenControlBehavior, MicrowaveOvenModeServer, TemperatureControlBehavior, } from 'matterbridge/matter/behaviors';
|
5
5
|
export class Appliances extends MatterbridgeEndpoint {
|
6
6
|
constructor(deviceType, name, serial) {
|
7
7
|
super([deviceType, powerSource], { uniqueStorageKey: `${name}-${serial}` }, true);
|
@@ -111,21 +111,6 @@ export class Appliances extends MatterbridgeEndpoint {
|
|
111
111
|
});
|
112
112
|
}
|
113
113
|
}
|
114
|
-
createDefaultOperationalStateClusterServer(operationalState = OperationalState.OperationalStateEnum.Stopped) {
|
115
|
-
this.behaviors.require(MatterbridgeOperationalStateServer, {
|
116
|
-
phaseList: [],
|
117
|
-
currentPhase: null,
|
118
|
-
operationalStateList: [
|
119
|
-
{ operationalStateId: OperationalState.OperationalStateEnum.Stopped, operationalStateLabel: 'Stopped' },
|
120
|
-
{ operationalStateId: OperationalState.OperationalStateEnum.Running, operationalStateLabel: 'Running' },
|
121
|
-
{ operationalStateId: OperationalState.OperationalStateEnum.Paused, operationalStateLabel: 'Paused' },
|
122
|
-
{ operationalStateId: OperationalState.OperationalStateEnum.Error, operationalStateLabel: 'Error' },
|
123
|
-
],
|
124
|
-
operationalState,
|
125
|
-
operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
126
|
-
});
|
127
|
-
return this;
|
128
|
-
}
|
129
114
|
createDefaultOvenCavityOperationalStateClusterServer(operationalState = OperationalState.OperationalStateEnum.Stopped) {
|
130
115
|
this.behaviors.require(OvenCavityOperationalStateServer, {
|
131
116
|
phaseList: [],
|
@@ -288,50 +273,6 @@ export class Appliances extends MatterbridgeEndpoint {
|
|
288
273
|
return endpoint;
|
289
274
|
}
|
290
275
|
}
|
291
|
-
class MatterbridgeOperationalStateServer extends OperationalStateBehavior {
|
292
|
-
initialize() {
|
293
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
294
|
-
device.log.info('MatterbridgeOperationalStateServer initialized: setting operational state to Stopped');
|
295
|
-
this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
|
296
|
-
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
297
|
-
}
|
298
|
-
pause() {
|
299
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
300
|
-
device.log.info('MatterbridgeOperationalStateServer: pause called setting operational state to Paused');
|
301
|
-
this.state.operationalState = OperationalState.OperationalStateEnum.Paused;
|
302
|
-
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
303
|
-
return {
|
304
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
305
|
-
};
|
306
|
-
}
|
307
|
-
stop() {
|
308
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
309
|
-
device.log.info('MatterbridgeOperationalStateServer: stop called setting operational state to Stopped');
|
310
|
-
this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
|
311
|
-
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
312
|
-
return {
|
313
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
314
|
-
};
|
315
|
-
}
|
316
|
-
start() {
|
317
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
318
|
-
device.log.info('MatterbridgeOperationalStateServer: start called setting operational state to Running');
|
319
|
-
this.state.operationalState = OperationalState.OperationalStateEnum.Running;
|
320
|
-
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
321
|
-
return {
|
322
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
323
|
-
};
|
324
|
-
}
|
325
|
-
resume() {
|
326
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
327
|
-
device.log.info('MatterbridgeOperationalStateServer: resume called setting operational state to Running');
|
328
|
-
this.state.operationalState = OperationalState.OperationalStateEnum.Running;
|
329
|
-
this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
|
330
|
-
return {
|
331
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
332
|
-
};
|
333
|
-
}
|
334
|
-
}
|
335
276
|
class MatterbridgeLevelTemperatureControlServer extends TemperatureControlBehavior.with(TemperatureControl.Feature.TemperatureLevel) {
|
336
277
|
initialize() {
|
337
278
|
if (this.state.supportedTemperatureLevels.length >= 2) {
|
package/dist/platform.js
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, bridgedNode, colorTemperatureLight, coverDevice, dimmableLight, doorLockDevice, fanDevice, flowSensor, humiditySensor, onOffLight, onOffOutlet, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, temperatureSensor, thermostatDevice, waterFreezeDetector, waterLeakDetector, airPurifier, pumpDevice, waterValve, genericSwitch, airConditioner, laundryWasher, cooktop, extractorHood, microwaveOven, oven, refrigerator, dishwasher, laundryDryer, onOffMountedSwitch, dimmableMountedSwitch, extendedColorLight, } from 'matterbridge';
|
1
|
+
import { MatterbridgeEndpoint, MatterbridgeDynamicPlatform, airQualitySensor, bridgedNode, colorTemperatureLight, coverDevice, dimmableLight, doorLockDevice, fanDevice, flowSensor, humiditySensor, onOffLight, onOffOutlet, onOffSwitch, powerSource, rainSensor, smokeCoAlarm, temperatureSensor, thermostatDevice, waterFreezeDetector, waterLeakDetector, airPurifier, pumpDevice, waterValve, genericSwitch, airConditioner, laundryWasher, cooktop, extractorHood, microwaveOven, oven, refrigerator, dishwasher, laundryDryer, onOffMountedSwitch, dimmableMountedSwitch, extendedColorLight, RoboticVacuumCleaner, WaterHeater, } from 'matterbridge';
|
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
5
|
import { Appliances } from './appliances.js';
|
6
|
-
import { Robot } from './robot.js';
|
7
6
|
export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatform {
|
8
7
|
switch;
|
9
8
|
mountedOnOffSwitch;
|
@@ -35,6 +34,7 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
35
34
|
momentarySwitch;
|
36
35
|
latchingSwitch;
|
37
36
|
vacuum;
|
37
|
+
heater;
|
38
38
|
switchInterval;
|
39
39
|
lightInterval;
|
40
40
|
outletInterval;
|
@@ -57,16 +57,14 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
57
57
|
fanModeLookup = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Smart'];
|
58
58
|
constructor(matterbridge, log, config) {
|
59
59
|
super(matterbridge, log, config);
|
60
|
-
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.
|
61
|
-
throw new Error(`This plugin requires Matterbridge version >= "3.0.
|
60
|
+
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.3')) {
|
61
|
+
throw new Error(`This plugin requires Matterbridge version >= "3.0.3". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
|
62
62
|
}
|
63
63
|
this.log.info('Initializing platform:', this.config.name);
|
64
64
|
if (config.whiteList === undefined)
|
65
65
|
config.whiteList = [];
|
66
66
|
if (config.blackList === undefined)
|
67
67
|
config.blackList = [];
|
68
|
-
if (config.enableConcentrationMeasurements === undefined)
|
69
|
-
config.enableConcentrationMeasurements = false;
|
70
68
|
if (config.enableRVC === undefined)
|
71
69
|
config.enableRVC = false;
|
72
70
|
}
|
@@ -720,11 +718,15 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
720
718
|
});
|
721
719
|
this.pump?.addCommandHandler('on', async () => {
|
722
720
|
this.pump?.log.info('Command on called');
|
723
|
-
await this.pump?.setAttribute(OnOff.Cluster.id, 'onOff', true, this.pump?.log);
|
724
721
|
});
|
725
722
|
this.pump?.addCommandHandler('off', async () => {
|
726
723
|
this.pump?.log.info('Command off called');
|
727
|
-
|
724
|
+
});
|
725
|
+
this.pump?.addCommandHandler('moveToLevel', async ({ request: { level } }) => {
|
726
|
+
this.pump?.log.info(`Command moveToLevel called request: ${level}`);
|
727
|
+
});
|
728
|
+
this.pump?.addCommandHandler('moveToLevelWithOnOff', async ({ request: { level } }) => {
|
729
|
+
this.pump?.log.info(`Command moveToLevelWithOnOff called request: ${level}`);
|
728
730
|
});
|
729
731
|
this.valve = new MatterbridgeEndpoint([waterValve, bridgedNode, powerSource], { uniqueStorageKey: 'Water valve' }, this.config.debug)
|
730
732
|
.createDefaultBridgedDeviceBasicInformationClusterServer('Water valve', '0x96382864WV', 0xfff1, 'Matterbridge', 'Matterbridge Water valve', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
|
@@ -837,9 +839,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
837
839
|
.createDefaultBridgedDeviceBasicInformationClusterServer('SmokeCo alarm sensor', 'serial_94745631225', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
|
838
840
|
.createDefaultIdentifyClusterServer()
|
839
841
|
.createDefaultSmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal, SmokeCoAlarm.AlarmState.Normal)
|
840
|
-
.createDefaultPowerSourceReplaceableBatteryClusterServer()
|
841
|
-
|
842
|
-
this.smokeCo.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
|
842
|
+
.createDefaultPowerSourceReplaceableBatteryClusterServer()
|
843
|
+
.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
|
843
844
|
this.setSelectDevice(this.smokeCo.serialNumber ?? '', this.smokeCo.deviceName ?? '', undefined, 'hub');
|
844
845
|
if (this.validateDevice(this.smokeCo.deviceName ?? '')) {
|
845
846
|
await this.registerDevice(this.smokeCo);
|
@@ -865,9 +866,8 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
865
866
|
.createDefaultBridgedDeviceBasicInformationClusterServer('Co alarm sensor', 'serial_947456317488', 0xfff1, 'Matterbridge', 'Matterbridge SmokeCoAlarm', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
|
866
867
|
.createDefaultIdentifyClusterServer()
|
867
868
|
.createCoOnlySmokeCOAlarmClusterServer(SmokeCoAlarm.AlarmState.Normal)
|
868
|
-
.createDefaultPowerSourceReplaceableBatteryClusterServer()
|
869
|
-
|
870
|
-
this.coOnly.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
|
869
|
+
.createDefaultPowerSourceReplaceableBatteryClusterServer()
|
870
|
+
.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(100);
|
871
871
|
this.setSelectDevice(this.coOnly.serialNumber ?? '', this.coOnly.deviceName ?? '', undefined, 'hub');
|
872
872
|
if (this.validateDevice(this.coOnly.deviceName ?? '')) {
|
873
873
|
await this.registerDevice(this.coOnly);
|
@@ -880,19 +880,17 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
880
880
|
.createDefaultBridgedDeviceBasicInformationClusterServer('Air quality sensor', 'serial_987484318322', 0xfff1, 'Matterbridge', 'Matterbridge Air Quality Sensor', parseInt(this.version.replace(/\D/g, '')), this.version === '' ? 'Unknown' : this.version, parseInt(this.matterbridge.matterbridgeVersion.replace(/\D/g, '')), this.matterbridge.matterbridgeVersion)
|
881
881
|
.createDefaultPowerSourceReplaceableBatteryClusterServer(50, PowerSource.BatChargeLevel.Warning, 2900, 'CR2450', 1)
|
882
882
|
.addRequiredClusterServers()
|
883
|
-
.addClusterServers([TemperatureMeasurement.Cluster.id, RelativeHumidityMeasurement.Cluster.id])
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
this.airQuality.createDefaultTvocMeasurementClusterServer(100);
|
895
|
-
}
|
883
|
+
.addClusterServers([TemperatureMeasurement.Cluster.id, RelativeHumidityMeasurement.Cluster.id])
|
884
|
+
.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer(10)
|
885
|
+
.createDefaultCarbonDioxideConcentrationMeasurementClusterServer(400)
|
886
|
+
.createDefaultNitrogenDioxideConcentrationMeasurementClusterServer(1)
|
887
|
+
.createDefaultOzoneConcentrationMeasurementClusterServer(1)
|
888
|
+
.createDefaultFormaldehydeConcentrationMeasurementClusterServer(1)
|
889
|
+
.createDefaultPm1ConcentrationMeasurementClusterServer(100)
|
890
|
+
.createDefaultPm25ConcentrationMeasurementClusterServer(100)
|
891
|
+
.createDefaultPm10ConcentrationMeasurementClusterServer(100)
|
892
|
+
.createDefaultRadonConcentrationMeasurementClusterServer(100)
|
893
|
+
.createDefaultTvocMeasurementClusterServer(100);
|
896
894
|
this.setSelectDevice(this.airQuality.serialNumber ?? '', this.airQuality.deviceName ?? '', undefined, 'hub');
|
897
895
|
if (this.validateDevice(this.airQuality.deviceName ?? '')) {
|
898
896
|
await this.registerDevice(this.airQuality);
|
@@ -928,13 +926,19 @@ export class ExampleMatterbridgeDynamicPlatform extends MatterbridgeDynamicPlatf
|
|
928
926
|
this.latchingSwitch = undefined;
|
929
927
|
}
|
930
928
|
if (this.config.enableRVC === true) {
|
931
|
-
const robot = new
|
929
|
+
const robot = new RoboticVacuumCleaner('Robot Vacuum', '1238777820');
|
932
930
|
this.setSelectDevice(robot.serialNumber ?? '', robot.deviceName ?? '', undefined, 'hub');
|
933
931
|
if (this.validateDevice(robot.deviceName ?? '')) {
|
934
932
|
await this.registerDevice(robot);
|
935
933
|
this.bridgedDevices.set(robot.deviceName ?? '', robot);
|
936
934
|
}
|
937
935
|
}
|
936
|
+
const heater = new WaterHeater('Water Heater', '3456177820');
|
937
|
+
this.setSelectDevice(heater.serialNumber ?? '', heater.deviceName ?? '', undefined, 'hub');
|
938
|
+
if (this.validateDevice(heater.deviceName ?? '')) {
|
939
|
+
await this.registerDevice(heater);
|
940
|
+
this.bridgedDevices.set(heater.deviceName ?? '', heater);
|
941
|
+
}
|
938
942
|
const laundryWasherDevice = new Appliances(laundryWasher, 'Laundry Washer', '1234567890');
|
939
943
|
this.setSelectDevice(laundryWasherDevice.serialNumber ?? '', laundryWasherDevice.deviceName ?? '', undefined, 'hub');
|
940
944
|
if (this.validateDevice(laundryWasherDevice.deviceName ?? '')) {
|
@@ -39,13 +39,8 @@
|
|
39
39
|
"type": "boolean",
|
40
40
|
"default": true
|
41
41
|
},
|
42
|
-
"enableConcentrationMeasurements": {
|
43
|
-
"description": "Enable the ConcentrationMeasurements in the Air Quality device and SmokeCoSensor device (Apple Home 18.4 will discard these devices when enabled)",
|
44
|
-
"type": "boolean",
|
45
|
-
"default": false
|
46
|
-
},
|
47
42
|
"enableRVC": {
|
48
|
-
"description": "Enable the Robot Vacuum Cleaner (Apple Home
|
43
|
+
"description": "Enable the Robot Vacuum Cleaner (Apple Home will crash unless you use child bridge and put the rvc in the white list as a single device)",
|
49
44
|
"type": "boolean",
|
50
45
|
"default": false
|
51
46
|
},
|
package/npm-shrinkwrap.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "matterbridge-example-dynamic-platform",
|
3
|
-
"version": "1.2.
|
3
|
+
"version": "1.2.2",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "matterbridge-example-dynamic-platform",
|
9
|
-
"version": "1.2.
|
9
|
+
"version": "1.2.2",
|
10
10
|
"license": "MIT",
|
11
11
|
"dependencies": {
|
12
12
|
"node-ansi-logger": "3.0.1",
|
package/package.json
CHANGED
package/dist/robot.js
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
import { Matterbridge, MatterbridgeServer, MatterbridgeEndpoint, roboticVacuumCleaner, dishwasher } from 'matterbridge';
|
2
|
-
import { LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, DeviceTypeId, VendorId, } from 'matterbridge/matter';
|
3
|
-
import { ModeBase, OperationalState, PowerSource, RvcRunMode, RvcCleanMode, RvcOperationalState, ServiceArea } from 'matterbridge/matter/clusters';
|
4
|
-
import { ActionsServer, RvcCleanModeBehavior, RvcOperationalStateBehavior, RvcRunModeBehavior, ServiceAreaBehavior } from 'matterbridge/matter/behaviors';
|
5
|
-
import { AnsiLogger } from 'matterbridge/logger';
|
6
|
-
export class Robot extends MatterbridgeEndpoint {
|
7
|
-
constructor(name, serial) {
|
8
|
-
super(roboticVacuumCleaner, { uniqueStorageKey: `${name}-${serial}` }, true);
|
9
|
-
this.createDefaultIdentifyClusterServer()
|
10
|
-
.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Robot Vacuum Cleaner')
|
11
|
-
.createDefaultRvcRunModeClusterServer()
|
12
|
-
.createDefaultRvcOperationalStateClusterServer()
|
13
|
-
.createDefaultRvcCleanModeClusterServer()
|
14
|
-
.createDefaultServiceAreaClusterServer()
|
15
|
-
.createDefaultPowerSourceRechargeableBatteryClusterServer(80, PowerSource.BatChargeLevel.Ok, 5900);
|
16
|
-
}
|
17
|
-
createDefaultRvcRunModeClusterServer(currentMode, supportedModes) {
|
18
|
-
this.behaviors.require(MatterbridgeRvcRunModeServer, {
|
19
|
-
supportedModes: supportedModes ?? [
|
20
|
-
{ label: 'Idle', mode: 1, modeTags: [{ value: RvcRunMode.ModeTag.Idle }] },
|
21
|
-
{ label: 'Cleaning', mode: 2, modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }] },
|
22
|
-
{ label: 'Mapping', mode: 3, modeTags: [{ value: RvcRunMode.ModeTag.Mapping }] },
|
23
|
-
{ label: 'SpotCleaning', mode: 4, modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }, { value: RvcRunMode.ModeTag.Max }] },
|
24
|
-
],
|
25
|
-
currentMode: currentMode ?? 1,
|
26
|
-
});
|
27
|
-
return this;
|
28
|
-
}
|
29
|
-
createDefaultRvcCleanModeClusterServer(currentMode, supportedModes) {
|
30
|
-
this.behaviors.require(MatterbridgeRvcCleanModeServer, {
|
31
|
-
supportedModes: supportedModes ?? [
|
32
|
-
{ label: 'Vacuum', mode: 1, modeTags: [{ value: RvcCleanMode.ModeTag.Vacuum }] },
|
33
|
-
{ label: 'Mop', mode: 2, modeTags: [{ value: RvcCleanMode.ModeTag.Mop }] },
|
34
|
-
{ label: 'Clean', mode: 3, modeTags: [{ value: RvcCleanMode.ModeTag.DeepClean }] },
|
35
|
-
],
|
36
|
-
currentMode: currentMode ?? 1,
|
37
|
-
});
|
38
|
-
return this;
|
39
|
-
}
|
40
|
-
createDefaultServiceAreaClusterServer(supportedAreas, selectedAreas) {
|
41
|
-
this.behaviors.require(MatterbridgeServiceAreaServer, {
|
42
|
-
supportedAreas: supportedAreas ?? [
|
43
|
-
{
|
44
|
-
areaId: 1,
|
45
|
-
mapId: null,
|
46
|
-
areaInfo: { locationInfo: { locationName: 'Living', floorNumber: null, areaType: null }, landmarkInfo: null },
|
47
|
-
},
|
48
|
-
{
|
49
|
-
areaId: 2,
|
50
|
-
mapId: null,
|
51
|
-
areaInfo: { locationInfo: { locationName: 'Kitchen', floorNumber: null, areaType: null }, landmarkInfo: null },
|
52
|
-
},
|
53
|
-
{
|
54
|
-
areaId: 3,
|
55
|
-
mapId: null,
|
56
|
-
areaInfo: { locationInfo: { locationName: 'Bedroom', floorNumber: null, areaType: null }, landmarkInfo: null },
|
57
|
-
},
|
58
|
-
{
|
59
|
-
areaId: 4,
|
60
|
-
mapId: null,
|
61
|
-
areaInfo: { locationInfo: { locationName: 'Bathroom', floorNumber: null, areaType: null }, landmarkInfo: null },
|
62
|
-
},
|
63
|
-
],
|
64
|
-
selectedAreas: selectedAreas ?? [],
|
65
|
-
currentArea: 1,
|
66
|
-
estimatedEndTime: null,
|
67
|
-
});
|
68
|
-
return this;
|
69
|
-
}
|
70
|
-
createDefaultRvcOperationalStateClusterServer(phaseList = null, currentPhase = null, operationalStateList, operationalState, operationalError) {
|
71
|
-
this.behaviors.require(MatterbridgeRvcOperationalStateServer, {
|
72
|
-
phaseList,
|
73
|
-
currentPhase,
|
74
|
-
operationalStateList: operationalStateList ?? [
|
75
|
-
{ operationalStateId: RvcOperationalState.OperationalState.Stopped, operationalStateLabel: 'Stopped' },
|
76
|
-
{ operationalStateId: RvcOperationalState.OperationalState.Running, operationalStateLabel: 'Running' },
|
77
|
-
{ operationalStateId: RvcOperationalState.OperationalState.Paused, operationalStateLabel: 'Paused' },
|
78
|
-
{ operationalStateId: RvcOperationalState.OperationalState.Error, operationalStateLabel: 'Error' },
|
79
|
-
{ operationalStateId: RvcOperationalState.OperationalState.SeekingCharger, operationalStateLabel: 'SeekingCharger' },
|
80
|
-
{ operationalStateId: RvcOperationalState.OperationalState.Charging, operationalStateLabel: 'Charging' },
|
81
|
-
{ operationalStateId: RvcOperationalState.OperationalState.Docked, operationalStateLabel: 'Docked' },
|
82
|
-
],
|
83
|
-
operationalState: operationalState ?? RvcOperationalState.OperationalState.Docked,
|
84
|
-
operationalError: operationalError ?? { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' },
|
85
|
-
});
|
86
|
-
return this;
|
87
|
-
}
|
88
|
-
}
|
89
|
-
export class MatterbridgeServiceAreaServer extends ServiceAreaBehavior {
|
90
|
-
initialize() {
|
91
|
-
}
|
92
|
-
selectAreas({ newAreas }) {
|
93
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
94
|
-
for (const area of newAreas) {
|
95
|
-
const supportedArea = this.state.supportedAreas.find((supportedArea) => supportedArea.areaId === area);
|
96
|
-
if (!supportedArea) {
|
97
|
-
device.log.error('MatterbridgeServiceAreaServer selectAreas called with unsupported area:', area);
|
98
|
-
return { status: ServiceArea.SelectAreasStatus.UnsupportedArea, statusText: 'Unsupported areas' };
|
99
|
-
}
|
100
|
-
}
|
101
|
-
this.state.selectedAreas = newAreas;
|
102
|
-
this.state.currentArea = newAreas[0];
|
103
|
-
device.log.info(`***MatterbridgeServiceAreaServer selectAreas called with: ${newAreas.map((area) => area.toString()).join(', ')}`);
|
104
|
-
return { status: ServiceArea.SelectAreasStatus.Success, statusText: 'Succesfully selected new areas' };
|
105
|
-
}
|
106
|
-
}
|
107
|
-
export class MatterbridgeRvcRunModeServer extends RvcRunModeBehavior {
|
108
|
-
initialize() {
|
109
|
-
this.state.currentMode = 1;
|
110
|
-
}
|
111
|
-
changeToMode({ newMode }) {
|
112
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
113
|
-
const changedMode = this.state.supportedModes.find((mode) => mode.mode === newMode);
|
114
|
-
if (!changedMode) {
|
115
|
-
device.log.error('MatterbridgeRvcRunModeServer changeToMode called with unsupported newMode:', newMode);
|
116
|
-
return { status: ModeBase.ModeChangeStatus.InvalidInMode, statusText: 'Invalid mode' };
|
117
|
-
}
|
118
|
-
device.changeToMode({ newMode });
|
119
|
-
this.state.currentMode = newMode;
|
120
|
-
if (changedMode.modeTags.find((tag) => tag.value === RvcRunMode.ModeTag.Cleaning)) {
|
121
|
-
device.log.info('***MatterbridgeRvcRunModeServer changeToMode called with newMode Cleaning => Running');
|
122
|
-
this.agent.get(MatterbridgeRvcOperationalStateServer).state.operationalState = RvcOperationalState.OperationalState.Running;
|
123
|
-
return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Running' };
|
124
|
-
}
|
125
|
-
else if (changedMode.modeTags.find((tag) => tag.value === RvcRunMode.ModeTag.Idle)) {
|
126
|
-
device.log.info('***MatterbridgeRvcRunModeServer changeToMode called with newMode Idle => Docked');
|
127
|
-
this.agent.get(MatterbridgeRvcOperationalStateServer).state.operationalState = RvcOperationalState.OperationalState.Docked;
|
128
|
-
return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Docked' };
|
129
|
-
}
|
130
|
-
device.log.info(`***MatterbridgeRvcRunModeServer changeToMode called with newMode ${newMode} => ${changedMode.label}`);
|
131
|
-
this.agent.get(MatterbridgeRvcOperationalStateServer).state.operationalState = RvcOperationalState.OperationalState.Running;
|
132
|
-
return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Success' };
|
133
|
-
}
|
134
|
-
}
|
135
|
-
export class MatterbridgeRvcCleanModeServer extends RvcCleanModeBehavior {
|
136
|
-
initialize() {
|
137
|
-
this.state.currentMode = 1;
|
138
|
-
}
|
139
|
-
changeToMode({ newMode }) {
|
140
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
141
|
-
const supported = this.state.supportedModes.find((mode) => mode.mode === newMode);
|
142
|
-
if (!supported) {
|
143
|
-
device.log.error('***MatterbridgeRvcCleanModeServer changeToMode called with unsupported newMode:', newMode);
|
144
|
-
return { status: ModeBase.ModeChangeStatus.InvalidInMode, statusText: 'Invalid mode' };
|
145
|
-
}
|
146
|
-
device.changeToMode({ newMode });
|
147
|
-
this.state.currentMode = newMode;
|
148
|
-
device.log.info(`***MatterbridgeRvcCleanModeServer changeToMode called with newMode ${newMode} => ${supported.label}`);
|
149
|
-
return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Success' };
|
150
|
-
}
|
151
|
-
}
|
152
|
-
export class MatterbridgeRvcOperationalStateServer extends RvcOperationalStateBehavior {
|
153
|
-
initialize() {
|
154
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
155
|
-
device.log.info('***MatterbridgeRvcOperationalStateServer initialized: setting operational state to Docked');
|
156
|
-
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
157
|
-
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
158
|
-
}
|
159
|
-
pause() {
|
160
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
161
|
-
device.log.info('MatterbridgeRvcOperationalStateServer: pause called setting operational state to Paused and currentMode to Idle');
|
162
|
-
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
163
|
-
this.state.operationalState = RvcOperationalState.OperationalState.Paused;
|
164
|
-
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
165
|
-
return {
|
166
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
167
|
-
};
|
168
|
-
}
|
169
|
-
resume() {
|
170
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
171
|
-
device.log.info('MatterbridgeRvcOperationalStateServer: resume called setting operational state to Running and currentMode to Cleaning');
|
172
|
-
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 2;
|
173
|
-
this.state.operationalState = RvcOperationalState.OperationalState.Running;
|
174
|
-
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
175
|
-
return {
|
176
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
177
|
-
};
|
178
|
-
}
|
179
|
-
goHome() {
|
180
|
-
const device = this.endpoint.stateOf(MatterbridgeServer).deviceCommand;
|
181
|
-
device.log.info('MatterbridgeRvcOperationalStateServer: goHome called setting operational state to Docked and currentMode to Idle');
|
182
|
-
this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
|
183
|
-
this.state.operationalState = RvcOperationalState.OperationalState.Docked;
|
184
|
-
this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
|
185
|
-
return {
|
186
|
-
commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
|
187
|
-
};
|
188
|
-
}
|
189
|
-
}
|
190
|
-
function createEndpointActionsClusterServer(endpoint, endpointLists) {
|
191
|
-
endpoint.behaviors.require(ActionsServer, {
|
192
|
-
actionList: [],
|
193
|
-
endpointLists,
|
194
|
-
});
|
195
|
-
return endpoint;
|
196
|
-
}
|
197
|
-
if (process.argv.includes('-testRobot')) {
|
198
|
-
const matterbridge = await Matterbridge.loadInstance(false);
|
199
|
-
matterbridge.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: "debug" });
|
200
|
-
matterbridge.environment.vars.set('log.level', MatterLogLevel.DEBUG);
|
201
|
-
matterbridge.environment.vars.set('log.format', MatterLogFormat.ANSI);
|
202
|
-
matterbridge.environment.vars.set('path.root', 'matterstorage');
|
203
|
-
matterbridge.environment.vars.set('runtime.signals', true);
|
204
|
-
matterbridge.environment.vars.set('runtime.exitcode', true);
|
205
|
-
matterbridge.environment.vars.set('mdns.networkInterface', 'Wi-Fi');
|
206
|
-
await matterbridge.startMatterStorage();
|
207
|
-
const deviceType = dishwasher;
|
208
|
-
const context = await matterbridge.createServerNodeContext('Matterbridge', deviceType.name, DeviceTypeId(deviceType.code), VendorId(0xfff1), 'Matterbridge', 0x8000, 'Matterbridge device');
|
209
|
-
const server = (await matterbridge.createServerNode(context));
|
210
|
-
}
|