matterbridge 3.0.3-dev-20250517-bcc5d13 → 3.0.3-dev-20250518-a216d52

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 CHANGED
@@ -12,6 +12,9 @@ If you like this project and find it useful, please consider giving it a star on
12
12
 
13
13
  ### Added
14
14
 
15
+ - [virtual] Added virtual devices configuration mode in the Matterbridge Settings: 'Disabled', 'Light', 'Outlet', 'Switch', 'Mounted_switch'. Switch is not supported by Alexa. Mounted Switch is not supported by Apple.
16
+ - [deviceTypes] Add waterHeater device type.
17
+
15
18
  ### Changed
16
19
 
17
20
  - [package]: Updated dependencies.
package/dist/frontend.js CHANGED
@@ -1431,6 +1431,15 @@ export class Frontend {
1431
1431
  }
1432
1432
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true }));
1433
1433
  break;
1434
+ case 'setvirtualmode':
1435
+ if (isValidString(data.params.value, 1) && ['disabled', 'light', 'outlet', 'switch', 'mounted_switch'].includes(data.params.value)) {
1436
+ this.matterbridge.matterbridgeInformation.virtualMode = data.params.value;
1437
+ this.log.debug(`Set matterbridge virtual mode to ${CYAN}${data.params.value}${db}`);
1438
+ await this.matterbridge.nodeContext?.set('virtualmode', data.params.value);
1439
+ this.wssSendRestartRequired();
1440
+ }
1441
+ client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true }));
1442
+ break;
1434
1443
  default:
1435
1444
  this.log.warn(`Unknown parameter ${data.params.name} in /api/config`);
1436
1445
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `Unknown parameter ${data.params.name} in /api/config` }));
package/dist/helpers.js CHANGED
@@ -4,9 +4,27 @@ import { BridgedDeviceBasicInformationServer } from '@matter/node/behaviors/brid
4
4
  import { OnOffBaseServer } from '@matter/node/behaviors/on-off';
5
5
  import { OnOffPlugInUnitDevice } from '@matter/node/devices/on-off-plug-in-unit';
6
6
  import { hasParameter } from './utils/commandLine.js';
7
- export async function addVirtualDevice(aggregatorEndpoint, name, callback) {
8
- const device = new Endpoint(OnOffPlugInUnitDevice.with(BridgedDeviceBasicInformationServer), {
9
- id: name.replaceAll(' ', ''),
7
+ import { MountedOnOffControlDevice } from '@matter/node/devices/mounted-on-off-control';
8
+ import { OnOffLightDevice } from '@matter/node/devices/on-off-light';
9
+ import { OnOffLightSwitchDevice } from '@matter/node/devices/on-off-light-switch';
10
+ export async function addVirtualDevice(aggregatorEndpoint, name, type, callback) {
11
+ let deviceType;
12
+ switch (type) {
13
+ case 'light':
14
+ deviceType = OnOffLightDevice.with(BridgedDeviceBasicInformationServer);
15
+ break;
16
+ case 'outlet':
17
+ deviceType = OnOffPlugInUnitDevice.with(BridgedDeviceBasicInformationServer);
18
+ break;
19
+ case 'switch':
20
+ deviceType = OnOffLightSwitchDevice.with(BridgedDeviceBasicInformationServer, OnOffBaseServer);
21
+ break;
22
+ case 'mounted_switch':
23
+ deviceType = MountedOnOffControlDevice.with(BridgedDeviceBasicInformationServer);
24
+ break;
25
+ }
26
+ const device = new Endpoint(deviceType, {
27
+ id: name.replaceAll(' ', '') + ':' + type,
10
28
  bridgedDeviceBasicInformation: { nodeLabel: name },
11
29
  onOff: { onOff: false, startUpOnOff: OnOff.StartUpOnOff.Off },
12
30
  });
@@ -21,15 +39,15 @@ export async function addVirtualDevice(aggregatorEndpoint, name, callback) {
21
39
  return device;
22
40
  }
23
41
  export async function addVirtualDevices(matterbridge, aggregatorEndpoint) {
24
- if (!hasParameter('novirtual') && matterbridge.bridgeMode === 'bridge' && aggregatorEndpoint) {
42
+ if (matterbridge.matterbridgeInformation.virtualMode !== 'disabled' && matterbridge.bridgeMode === 'bridge' && aggregatorEndpoint) {
25
43
  matterbridge.log.notice(`Creating virtual devices for Matterbridge server node...`);
26
- await addVirtualDevice(aggregatorEndpoint, 'Restart Matterbridge', async () => {
44
+ await addVirtualDevice(aggregatorEndpoint, 'Restart Matterbridge', matterbridge.matterbridgeInformation.virtualMode, async () => {
27
45
  if (matterbridge.restartMode === '')
28
46
  await matterbridge.restartProcess();
29
47
  else
30
48
  await matterbridge.shutdownProcess();
31
49
  });
32
- await addVirtualDevice(aggregatorEndpoint, 'Update Matterbridge', async () => {
50
+ await addVirtualDevice(aggregatorEndpoint, 'Update Matterbridge', matterbridge.matterbridgeInformation.virtualMode, async () => {
33
51
  if (hasParameter('shelly')) {
34
52
  const { getShelly } = await import('./shelly.js');
35
53
  getShelly('/api/updates/sys/perform', 10 * 1000)
@@ -52,7 +70,7 @@ export async function addVirtualDevices(matterbridge, aggregatorEndpoint) {
52
70
  }
53
71
  });
54
72
  if (hasParameter('shelly')) {
55
- await addVirtualDevice(aggregatorEndpoint, 'Reboot Matterbridge', async () => {
73
+ await addVirtualDevice(aggregatorEndpoint, 'Reboot Matterbridge', matterbridge.matterbridgeInformation.virtualMode, async () => {
56
74
  const { postShelly } = await import('./shelly.js');
57
75
  postShelly('/api/system/reboot', {}, 60 * 1000)
58
76
  .then(() => {
@@ -60,6 +60,7 @@ export class Matterbridge extends EventEmitter {
60
60
  matterbridgeAdvertise: false,
61
61
  bridgeMode: '',
62
62
  restartMode: '',
63
+ virtualMode: 'outlet',
63
64
  readOnly: hasParameter('readonly') || hasParameter('shelly'),
64
65
  shellyBoard: hasParameter('shelly'),
65
66
  shellySysUpdate: false,
@@ -474,6 +475,14 @@ export class Matterbridge extends EventEmitter {
474
475
  await this.nodeContext.remove('matteripv6address');
475
476
  }
476
477
  }
478
+ if (hasParameter('novirtual')) {
479
+ this.matterbridgeInformation.virtualMode = 'disabled';
480
+ await this.nodeContext.set('virtualmode', 'disabled');
481
+ }
482
+ else {
483
+ this.matterbridgeInformation.virtualMode = (await this.nodeContext.get('virtualmode', 'outlet'));
484
+ }
485
+ this.log.debug(`Virtual mode ${this.matterbridgeInformation.virtualMode}.`);
477
486
  this.plugins = new PluginManager(this);
478
487
  await this.plugins.loadFromStorage();
479
488
  this.plugins.logLevel = this.log.logLevel;
@@ -64,6 +64,8 @@ import { RefrigeratorAlarm } from '@matter/main/clusters/refrigerator-alarm';
64
64
  import { RefrigeratorAndTemperatureControlledCabinetMode } from '@matter/main/clusters/refrigerator-and-temperature-controlled-cabinet-mode';
65
65
  import { ServiceArea } from '@matter/main/clusters/service-area';
66
66
  import { TemperatureControl } from '@matter/main/clusters/temperature-control';
67
+ import { OtaSoftwareUpdateRequestor } from '@matter/main/clusters/ota-software-update-requestor';
68
+ import { EnergyEvse, EnergyEvseMode, OtaSoftwareUpdateProvider, WaterHeaterManagement, WaterHeaterMode } from '@matter/main/clusters';
67
69
  export var DeviceClasses;
68
70
  (function (DeviceClasses) {
69
71
  DeviceClasses["Node"] = "Node";
@@ -95,6 +97,26 @@ export const powerSource = DeviceTypeDefinition({
95
97
  requiredServerClusters: [PowerSource.Cluster.id],
96
98
  optionalServerClusters: [],
97
99
  });
100
+ export const OTARequestor = DeviceTypeDefinition({
101
+ name: 'MA-OTARequestor',
102
+ code: 0x0012,
103
+ deviceClass: DeviceClasses.Utility,
104
+ revision: 1,
105
+ requiredServerClusters: [OtaSoftwareUpdateRequestor.Cluster.id],
106
+ optionalServerClusters: [],
107
+ requiredClientClusters: [OtaSoftwareUpdateProvider.Cluster.id],
108
+ optionalClientClusters: [],
109
+ });
110
+ export const OTAProvider = DeviceTypeDefinition({
111
+ name: 'MA-OTAProvider',
112
+ code: 0x0014,
113
+ deviceClass: DeviceClasses.Utility,
114
+ revision: 1,
115
+ requiredServerClusters: [OtaSoftwareUpdateProvider.Cluster.id],
116
+ optionalServerClusters: [],
117
+ requiredClientClusters: [OtaSoftwareUpdateRequestor.Cluster.id],
118
+ optionalClientClusters: [],
119
+ });
98
120
  export const bridgedNode = DeviceTypeDefinition({
99
121
  name: 'MA-bridgedNode',
100
122
  code: 0x0013,
@@ -116,8 +138,8 @@ export const deviceEnergyManagement = DeviceTypeDefinition({
116
138
  code: 0x050d,
117
139
  deviceClass: DeviceClasses.Utility,
118
140
  revision: 2,
119
- requiredServerClusters: [DeviceEnergyManagement.Cluster.id, DeviceEnergyManagementMode.Cluster.id],
120
- optionalServerClusters: [],
141
+ requiredServerClusters: [DeviceEnergyManagement.Cluster.id],
142
+ optionalServerClusters: [DeviceEnergyManagementMode.Cluster.id],
121
143
  });
122
144
  export const onOffLight = DeviceTypeDefinition({
123
145
  name: 'MA-onofflight',
@@ -501,3 +523,43 @@ export const microwaveOven = DeviceTypeDefinition({
501
523
  requiredServerClusters: [OperationalState.Cluster.id, MicrowaveOvenMode.Cluster.id, MicrowaveOvenControl.Cluster.id],
502
524
  optionalServerClusters: [Identify.Cluster.id, FanControl.Cluster.id],
503
525
  });
526
+ export const evse = DeviceTypeDefinition({
527
+ name: 'MA-evse',
528
+ code: 0x050c,
529
+ deviceClass: DeviceClasses.Simple,
530
+ revision: 2,
531
+ requiredServerClusters: [EnergyEvse.Cluster.id, EnergyEvseMode.Cluster.id],
532
+ optionalServerClusters: [Identify.Cluster.id, TemperatureMeasurement.Cluster.id],
533
+ });
534
+ export const waterHeater = DeviceTypeDefinition({
535
+ name: 'MA-waterheater',
536
+ code: 0x050f,
537
+ deviceClass: DeviceClasses.Simple,
538
+ revision: 1,
539
+ requiredServerClusters: [Thermostat.Cluster.id, WaterHeaterManagement.Cluster.id, WaterHeaterMode.Cluster.id],
540
+ optionalServerClusters: [Identify.Cluster.id],
541
+ });
542
+ export const solarPower = DeviceTypeDefinition({
543
+ name: 'MA-solarpower',
544
+ code: 0x0017,
545
+ deviceClass: DeviceClasses.Simple,
546
+ revision: 1,
547
+ requiredServerClusters: [],
548
+ optionalServerClusters: [Identify.Cluster.id],
549
+ });
550
+ export const batteryStorage = DeviceTypeDefinition({
551
+ name: 'MA-batterystorage',
552
+ code: 0x0018,
553
+ deviceClass: DeviceClasses.Simple,
554
+ revision: 1,
555
+ requiredServerClusters: [],
556
+ optionalServerClusters: [Identify.Cluster.id],
557
+ });
558
+ export const heatPump = DeviceTypeDefinition({
559
+ name: 'MA-heatpump',
560
+ code: 0x0309,
561
+ deviceClass: DeviceClasses.Simple,
562
+ revision: 1,
563
+ requiredServerClusters: [],
564
+ optionalServerClusters: [Identify.Cluster.id, Thermostat.Cluster.id],
565
+ });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "./static/css/main.944b63c3.css",
4
- "main.js": "./static/js/main.f6e0f736.js",
4
+ "main.js": "./static/js/main.2486c3e3.js",
5
5
  "static/js/453.d855a71b.chunk.js": "./static/js/453.d855a71b.chunk.js",
6
6
  "static/media/roboto-latin-700-normal.woff2": "./static/media/roboto-latin-700-normal.c4d6cab43bec89049809.woff2",
7
7
  "static/media/roboto-latin-500-normal.woff2": "./static/media/roboto-latin-500-normal.599f66a60bdf974e578e.woff2",
@@ -77,11 +77,11 @@
77
77
  "static/media/roboto-greek-ext-300-normal.woff": "./static/media/roboto-greek-ext-300-normal.60729cafbded24073dfb.woff",
78
78
  "index.html": "./index.html",
79
79
  "main.944b63c3.css.map": "./static/css/main.944b63c3.css.map",
80
- "main.f6e0f736.js.map": "./static/js/main.f6e0f736.js.map",
80
+ "main.2486c3e3.js.map": "./static/js/main.2486c3e3.js.map",
81
81
  "453.d855a71b.chunk.js.map": "./static/js/453.d855a71b.chunk.js.map"
82
82
  },
83
83
  "entrypoints": [
84
84
  "static/css/main.944b63c3.css",
85
- "static/js/main.f6e0f736.js"
85
+ "static/js/main.2486c3e3.js"
86
86
  ]
87
87
  }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="./"><link rel="icon" href="./matterbridge 32x32.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Matterbridge</title><link rel="manifest" href="./manifest.json"/><script defer="defer" src="./static/js/main.f6e0f736.js"></script><link href="./static/css/main.944b63c3.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="./"><link rel="icon" href="./matterbridge 32x32.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Matterbridge</title><link rel="manifest" href="./manifest.json"/><script defer="defer" src="./static/js/main.2486c3e3.js"></script><link href="./static/css/main.944b63c3.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>