matterbridge 3.2.9-dev-20250924-9417698 → 3.2.9-dev-20250924-c639a33
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 +4 -0
- package/dist/frontend.js +10 -8
- package/dist/matterbridge.js +55 -11
- package/dist/matterbridgeEndpoint.js +16 -6
- package/dist/utils/spawn.js +4 -1
- package/frontend/build/assets/index.js +5 -1
- package/frontend/build/assets/vendor_mui.js +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,10 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
21
21
|
- [frontend]: Use MbfTable for Plugins, Devices, Registered devices and Clusters tables.
|
|
22
22
|
- [frontend]: Optimized WebSocker message handlers. Now, the handler targets the component.
|
|
23
23
|
- [frontend]: Removed dangerouslySetInnerHTML from log rendering.
|
|
24
|
+
- [frontend]: Added push update to Icon view and table view cluster panel.
|
|
25
|
+
- [frontend]: Added install progress dialog when installing or uploading packages.
|
|
26
|
+
- [endpoint]: Added occupancy feature to all Thermostat cluster helpers. When provided (either false or true) it will create a Thermostat with occupancy feature.
|
|
27
|
+
- [endpoint]: Added outdoorTemperature to all Thermostat cluster helpers. Default is undefined (it will be ignored).
|
|
24
28
|
|
|
25
29
|
### Changed
|
|
26
30
|
|
package/dist/frontend.js
CHANGED
|
@@ -525,7 +525,7 @@ export class Frontend extends EventEmitter {
|
|
|
525
525
|
this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
|
|
526
526
|
if (filename.endsWith('.tgz')) {
|
|
527
527
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
528
|
-
await spawnCommand(this.matterbridge, 'npm', ['install', '-g', filePath, '--omit=dev', '--verbose']);
|
|
528
|
+
await spawnCommand(this.matterbridge, 'npm', ['install', '-g', filePath, '--omit=dev', '--verbose'], filename);
|
|
529
529
|
this.log.info(`Plugin package ${plg}${filename}${nf} installed successfully. Full restart required.`);
|
|
530
530
|
this.wssSendCloseSnackbarMessage(`Installing package ${filename}. Please wait...`);
|
|
531
531
|
this.wssSendSnackbarMessage(`Installed package ${filename}`, 10, 'success');
|
|
@@ -856,7 +856,7 @@ export class Frontend extends EventEmitter {
|
|
|
856
856
|
}
|
|
857
857
|
getClusters(pluginName, endpointNumber) {
|
|
858
858
|
const endpoint = this.matterbridge.devices.array().find((d) => d.plugin === pluginName && d.maybeNumber === endpointNumber);
|
|
859
|
-
if (!endpoint || !endpoint.plugin || !endpoint.maybeNumber || !endpoint.deviceName || !endpoint.serialNumber) {
|
|
859
|
+
if (!endpoint || !endpoint.plugin || !endpoint.maybeNumber || !endpoint.maybeId || !endpoint.deviceName || !endpoint.serialNumber) {
|
|
860
860
|
this.log.error(`getClusters: no device found for plugin ${pluginName} and endpoint number ${endpointNumber}`);
|
|
861
861
|
return;
|
|
862
862
|
}
|
|
@@ -872,6 +872,7 @@ export class Frontend extends EventEmitter {
|
|
|
872
872
|
return;
|
|
873
873
|
clusters.push({
|
|
874
874
|
endpoint: endpoint.number.toString(),
|
|
875
|
+
number: endpoint.number,
|
|
875
876
|
id: 'main',
|
|
876
877
|
deviceTypes,
|
|
877
878
|
clusterName: capitalizeFirstLetter(clusterName),
|
|
@@ -899,7 +900,8 @@ export class Frontend extends EventEmitter {
|
|
|
899
900
|
return;
|
|
900
901
|
clusters.push({
|
|
901
902
|
endpoint: childEndpoint.number.toString(),
|
|
902
|
-
|
|
903
|
+
number: childEndpoint.number,
|
|
904
|
+
id: childEndpoint.id,
|
|
903
905
|
deviceTypes,
|
|
904
906
|
clusterName: capitalizeFirstLetter(clusterName),
|
|
905
907
|
clusterId: '0x' + clusterId.toString(16).padStart(2, '0'),
|
|
@@ -910,7 +912,7 @@ export class Frontend extends EventEmitter {
|
|
|
910
912
|
});
|
|
911
913
|
});
|
|
912
914
|
});
|
|
913
|
-
return { plugin: endpoint.plugin, deviceName: endpoint.deviceName, serialNumber: endpoint.serialNumber, endpoint: endpoint.
|
|
915
|
+
return { plugin: endpoint.plugin, deviceName: endpoint.deviceName, serialNumber: endpoint.serialNumber, number: endpoint.number, id: endpoint.id, deviceTypes, clusters };
|
|
914
916
|
}
|
|
915
917
|
async wsMessageHandler(client, message) {
|
|
916
918
|
let data;
|
|
@@ -967,7 +969,7 @@ export class Frontend extends EventEmitter {
|
|
|
967
969
|
}
|
|
968
970
|
this.wssSendSnackbarMessage(`Installing package ${data.params.packageName}...`, 0);
|
|
969
971
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
970
|
-
spawnCommand(this.matterbridge, 'npm', ['install', '-g', data.params.packageName, '--omit=dev', '--verbose'])
|
|
972
|
+
spawnCommand(this.matterbridge, 'npm', ['install', '-g', data.params.packageName, '--omit=dev', '--verbose'], data.params.packageName)
|
|
971
973
|
.then((_response) => {
|
|
972
974
|
sendResponse({ id: localData.id, method: localData.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
973
975
|
this.wssSendCloseSnackbarMessage(`Installing package ${localData.params.packageName}...`);
|
|
@@ -1035,7 +1037,7 @@ export class Frontend extends EventEmitter {
|
|
|
1035
1037
|
}
|
|
1036
1038
|
this.wssSendSnackbarMessage(`Uninstalling package ${data.params.packageName}...`, 0);
|
|
1037
1039
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
1038
|
-
spawnCommand(this.matterbridge, 'npm', ['uninstall', '-g', data.params.packageName, '--verbose'])
|
|
1040
|
+
spawnCommand(this.matterbridge, 'npm', ['uninstall', '-g', data.params.packageName, '--verbose'], data.params.packageName)
|
|
1039
1041
|
.then((_response) => {
|
|
1040
1042
|
sendResponse({ id: localData.id, method: localData.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1041
1043
|
this.wssSendCloseSnackbarMessage(`Uninstalling package ${localData.params.packageName}...`);
|
|
@@ -1765,9 +1767,9 @@ export class Frontend extends EventEmitter {
|
|
|
1765
1767
|
this.log.debug('Sending a close snackbar message to all connected clients');
|
|
1766
1768
|
this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'close_snackbar', success: true, response: { message } });
|
|
1767
1769
|
}
|
|
1768
|
-
wssSendAttributeChangedMessage(plugin, serialNumber, uniqueId, cluster, attribute, value) {
|
|
1770
|
+
wssSendAttributeChangedMessage(plugin, serialNumber, uniqueId, number, id, cluster, attribute, value) {
|
|
1769
1771
|
this.log.debug('Sending an attribute update message to all connected clients');
|
|
1770
|
-
this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', success: true, response: { plugin, serialNumber, uniqueId, cluster, attribute, value } });
|
|
1772
|
+
this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', success: true, response: { plugin, serialNumber, uniqueId, number, id, cluster, attribute, value } });
|
|
1771
1773
|
}
|
|
1772
1774
|
wssBroadcastMessage(msg) {
|
|
1773
1775
|
const stringifiedMsg = JSON.stringify(msg);
|
package/dist/matterbridge.js
CHANGED
|
@@ -3,13 +3,12 @@ import path from 'node:path';
|
|
|
3
3
|
import { promises as fs } from 'node:fs';
|
|
4
4
|
import EventEmitter from 'node:events';
|
|
5
5
|
import { inspect } from 'node:util';
|
|
6
|
-
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt, BLUE } from 'node-ansi-logger';
|
|
6
|
+
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt, BLUE, or } from 'node-ansi-logger';
|
|
7
7
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
8
8
|
import { DeviceTypeId, Endpoint, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, StorageService, Environment, ServerNode, UINT32_MAX, UINT16_MAX, Crypto, } from '@matter/main';
|
|
9
9
|
import { FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
|
|
10
10
|
import { AggregatorEndpoint } from '@matter/main/endpoints';
|
|
11
11
|
import { BasicInformationServer } from '@matter/main/behaviors/basic-information';
|
|
12
|
-
import { BridgedDeviceBasicInformationServer } from '@matter/main/behaviors/bridged-device-basic-information';
|
|
13
12
|
import { getParameter, getIntParameter, hasParameter, copyDirectory, isValidString, parseVersionString, isValidNumber, createDirectory } from './utils/export.js';
|
|
14
13
|
import { withTimeout, waiter, wait } from './utils/wait.js';
|
|
15
14
|
import { dev, plg, typ } from './matterbridgeTypes.js';
|
|
@@ -508,7 +507,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
508
507
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
|
|
509
508
|
try {
|
|
510
509
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
511
|
-
await spawnCommand(this, 'npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose']);
|
|
510
|
+
await spawnCommand(this, 'npm', ['install', '-g', plugin.name, '--omit=dev', '--verbose'], plugin.name);
|
|
512
511
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
513
512
|
plugin.error = false;
|
|
514
513
|
}
|
|
@@ -950,7 +949,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
950
949
|
this.log.info('Updating matterbridge...');
|
|
951
950
|
try {
|
|
952
951
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
953
|
-
await spawnCommand(this, 'npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose']);
|
|
952
|
+
await spawnCommand(this, 'npm', ['install', '-g', 'matterbridge', '--omit=dev', '--verbose'], 'matterbridge');
|
|
954
953
|
this.log.info('Matterbridge has been updated. Full restart required.');
|
|
955
954
|
}
|
|
956
955
|
catch (error) {
|
|
@@ -1714,20 +1713,65 @@ export class Matterbridge extends EventEmitter {
|
|
|
1714
1713
|
await wait(2000);
|
|
1715
1714
|
}
|
|
1716
1715
|
async subscribeAttributeChanged(plugin, device) {
|
|
1717
|
-
if (!plugin || !device || !device.plugin || !device.serialNumber || !device.uniqueId)
|
|
1716
|
+
if (!plugin || !device || !device.plugin || !device.serialNumber || !device.uniqueId || !device.maybeNumber)
|
|
1718
1717
|
return;
|
|
1719
1718
|
this.log.info(`Subscribing attributes for endpoint ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) plugin ${plg}${plugin.name}${nf}`);
|
|
1720
1719
|
if (this.bridgeMode === 'childbridge' && plugin.type === 'AccessoryPlatform' && plugin.serverNode) {
|
|
1721
1720
|
plugin.serverNode.eventsOf(BasicInformationServer).reachable$Changed?.on((reachable) => {
|
|
1722
1721
|
this.log.info(`Accessory endpoint ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) is ${reachable ? 'reachable' : 'unreachable'}`);
|
|
1723
|
-
this.frontend.wssSendAttributeChangedMessage(device.plugin, device.serialNumber, device.uniqueId, '
|
|
1722
|
+
this.frontend.wssSendAttributeChangedMessage(device.plugin, device.serialNumber, device.uniqueId, device.number, device.id, 'BasicInformation', 'reachable', reachable);
|
|
1724
1723
|
});
|
|
1725
1724
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
}
|
|
1725
|
+
const subscriptions = [
|
|
1726
|
+
{ cluster: 'BridgedDeviceBasicInformation', attribute: 'reachable' },
|
|
1727
|
+
{ cluster: 'OnOff', attribute: 'onOff' },
|
|
1728
|
+
{ cluster: 'LevelControl', attribute: 'currentLevel' },
|
|
1729
|
+
{ cluster: 'ColorControl', attribute: 'colorMode' },
|
|
1730
|
+
{ cluster: 'ColorControl', attribute: 'currentHue' },
|
|
1731
|
+
{ cluster: 'ColorControl', attribute: 'currentSaturation' },
|
|
1732
|
+
{ cluster: 'ColorControl', attribute: 'currentX' },
|
|
1733
|
+
{ cluster: 'ColorControl', attribute: 'currentY' },
|
|
1734
|
+
{ cluster: 'ColorControl', attribute: 'colorTemperatureMireds' },
|
|
1735
|
+
{ cluster: 'Thermostat', attribute: 'localTemperature' },
|
|
1736
|
+
{ cluster: 'Thermostat', attribute: 'occupiedCoolingSetpoint' },
|
|
1737
|
+
{ cluster: 'Thermostat', attribute: 'occupiedHeatingSetpoint' },
|
|
1738
|
+
{ cluster: 'Thermostat', attribute: 'systemMode' },
|
|
1739
|
+
{ cluster: 'WindowCovering', attribute: 'operationalStatus' },
|
|
1740
|
+
{ cluster: 'WindowCovering', attribute: 'currentPositionLiftPercent100ths' },
|
|
1741
|
+
{ cluster: 'DoorLock', attribute: 'lockState' },
|
|
1742
|
+
{ cluster: 'PumpConfigurationAndControl', attribute: 'pumpStatus' },
|
|
1743
|
+
{ cluster: 'FanControl', attribute: 'fanMode' },
|
|
1744
|
+
{ cluster: 'FanControl', attribute: 'fanModeSequence' },
|
|
1745
|
+
{ cluster: 'FanControl', attribute: 'percentSetting' },
|
|
1746
|
+
{ cluster: 'AirQuality', attribute: 'airQuality' },
|
|
1747
|
+
{ cluster: 'TotalVolatileOrganicCompoundsConcentrationMeasurement', attribute: 'measuredValue' },
|
|
1748
|
+
{ cluster: 'BooleanState', attribute: 'stateValue' },
|
|
1749
|
+
{ cluster: 'OccupancySensing', attribute: 'occupancy' },
|
|
1750
|
+
{ cluster: 'IlluminanceMeasurement', attribute: 'measuredValue' },
|
|
1751
|
+
{ cluster: 'TemperatureMeasurement', attribute: 'measuredValue' },
|
|
1752
|
+
{ cluster: 'RelativeHumidityMeasurement', attribute: 'measuredValue' },
|
|
1753
|
+
{ cluster: 'PressureMeasurement', attribute: 'measuredValue' },
|
|
1754
|
+
{ cluster: 'FlowMeasurement', attribute: 'measuredValue' },
|
|
1755
|
+
];
|
|
1756
|
+
for (const sub of subscriptions) {
|
|
1757
|
+
if (device.hasAttributeServer(sub.cluster, sub.attribute)) {
|
|
1758
|
+
this.log.debug(`Subscribing to endpoint ${or}${device.id}${db}:${or}${device.number}${db} attribute ${dev}${sub.cluster}${db}.${dev}${sub.attribute}${db} changes...`);
|
|
1759
|
+
await device.subscribeAttribute(sub.cluster, sub.attribute, (value) => {
|
|
1760
|
+
this.log.debug(`Bridged endpoint ${or}${device.id}${db}:${or}${device.number}${db} attribute ${dev}${sub.cluster}${db}.${dev}${sub.attribute}${db} changed to ${CYAN}${value}${db}`);
|
|
1761
|
+
this.frontend.wssSendAttributeChangedMessage(device.plugin, device.serialNumber, device.uniqueId, device.number, device.id, sub.cluster, sub.attribute, value);
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1764
|
+
for (const child of device.getChildEndpoints()) {
|
|
1765
|
+
for (const sub of subscriptions) {
|
|
1766
|
+
if (child.hasAttributeServer(sub.cluster, sub.attribute)) {
|
|
1767
|
+
this.log.debug(`Subscribing to child endpoint ${or}${child.id}${db}:${or}${child.number}${db} attribute ${dev}${sub.cluster}${db}.${dev}${sub.attribute}${db} changes...`);
|
|
1768
|
+
await child.subscribeAttribute(sub.cluster, sub.attribute, (value) => {
|
|
1769
|
+
this.log.debug(`Bridged child endpoint ${or}${child.id}${db}:${or}${child.number}${db} attribute ${dev}${sub.cluster}${db}.${dev}${sub.attribute}${db} changed to ${CYAN}${value}${db}`);
|
|
1770
|
+
this.frontend.wssSendAttributeChangedMessage(device.plugin, device.serialNumber, device.uniqueId, child.number, child.id, sub.cluster, sub.attribute, value);
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1731
1775
|
}
|
|
1732
1776
|
}
|
|
1733
1777
|
sanitizeFabricInformations(fabricInfo) {
|
|
@@ -778,9 +778,10 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
778
778
|
this.log.debug(`Set WindowCovering currentPositionTiltPercent100ths: ${tiltPosition} and targetPositionTiltPercent100ths: ${tiltPosition}.`);
|
|
779
779
|
}
|
|
780
780
|
}
|
|
781
|
-
createDefaultThermostatClusterServer(localTemperature = 23, occupiedHeatingSetpoint = 21, occupiedCoolingSetpoint = 25, minSetpointDeadBand = 1, minHeatSetpointLimit = 0, maxHeatSetpointLimit = 50, minCoolSetpointLimit = 0, maxCoolSetpointLimit = 50) {
|
|
782
|
-
this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Heating, Thermostat.Feature.Cooling, Thermostat.Feature.AutoMode), {
|
|
781
|
+
createDefaultThermostatClusterServer(localTemperature = 23, occupiedHeatingSetpoint = 21, occupiedCoolingSetpoint = 25, minSetpointDeadBand = 1, minHeatSetpointLimit = 0, maxHeatSetpointLimit = 50, minCoolSetpointLimit = 0, maxCoolSetpointLimit = 50, unoccupiedHeatingSetpoint = undefined, unoccupiedCoolingSetpoint = undefined, occupied = undefined, outdoorTemperature = undefined) {
|
|
782
|
+
this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Heating, Thermostat.Feature.Cooling, Thermostat.Feature.AutoMode, ...(occupied !== undefined ? [Thermostat.Feature.Occupancy] : [])), {
|
|
783
783
|
localTemperature: localTemperature * 100,
|
|
784
|
+
...(outdoorTemperature !== undefined ? { outdoorTemperature: outdoorTemperature !== null ? outdoorTemperature * 100 : outdoorTemperature } : {}),
|
|
784
785
|
systemMode: Thermostat.SystemMode.Auto,
|
|
785
786
|
controlSequenceOfOperation: Thermostat.ControlSequenceOfOperation.CoolingAndHeating,
|
|
786
787
|
occupiedHeatingSetpoint: occupiedHeatingSetpoint * 100,
|
|
@@ -795,12 +796,16 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
795
796
|
absMaxCoolSetpointLimit: maxCoolSetpointLimit * 100,
|
|
796
797
|
minSetpointDeadBand: minSetpointDeadBand * 100,
|
|
797
798
|
thermostatRunningMode: Thermostat.ThermostatRunningMode.Off,
|
|
799
|
+
...(occupied !== undefined ? { unoccupiedHeatingSetpoint: unoccupiedHeatingSetpoint !== undefined ? unoccupiedHeatingSetpoint * 100 : 1900 } : {}),
|
|
800
|
+
...(occupied !== undefined ? { unoccupiedCoolingSetpoint: unoccupiedCoolingSetpoint !== undefined ? unoccupiedCoolingSetpoint * 100 : 2700 } : {}),
|
|
801
|
+
...(occupied !== undefined ? { occupancy: { occupied } } : {}),
|
|
798
802
|
});
|
|
799
803
|
return this;
|
|
800
804
|
}
|
|
801
|
-
createDefaultHeatingThermostatClusterServer(localTemperature = 23, occupiedHeatingSetpoint = 21, minHeatSetpointLimit = 0, maxHeatSetpointLimit = 50) {
|
|
802
|
-
this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Heating), {
|
|
805
|
+
createDefaultHeatingThermostatClusterServer(localTemperature = 23, occupiedHeatingSetpoint = 21, minHeatSetpointLimit = 0, maxHeatSetpointLimit = 50, unoccupiedHeatingSetpoint = undefined, occupied = undefined, outdoorTemperature = undefined) {
|
|
806
|
+
this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Heating, ...(occupied !== undefined ? [Thermostat.Feature.Occupancy] : [])), {
|
|
803
807
|
localTemperature: localTemperature * 100,
|
|
808
|
+
...(outdoorTemperature !== undefined ? { outdoorTemperature: outdoorTemperature !== null ? outdoorTemperature * 100 : outdoorTemperature } : {}),
|
|
804
809
|
systemMode: Thermostat.SystemMode.Heat,
|
|
805
810
|
controlSequenceOfOperation: Thermostat.ControlSequenceOfOperation.HeatingOnly,
|
|
806
811
|
occupiedHeatingSetpoint: occupiedHeatingSetpoint * 100,
|
|
@@ -808,12 +813,15 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
808
813
|
maxHeatSetpointLimit: maxHeatSetpointLimit * 100,
|
|
809
814
|
absMinHeatSetpointLimit: minHeatSetpointLimit * 100,
|
|
810
815
|
absMaxHeatSetpointLimit: maxHeatSetpointLimit * 100,
|
|
816
|
+
...(occupied !== undefined ? { unoccupiedHeatingSetpoint: unoccupiedHeatingSetpoint !== undefined ? unoccupiedHeatingSetpoint * 100 : 1900 } : {}),
|
|
817
|
+
...(occupied !== undefined ? { occupancy: { occupied } } : {}),
|
|
811
818
|
});
|
|
812
819
|
return this;
|
|
813
820
|
}
|
|
814
|
-
createDefaultCoolingThermostatClusterServer(localTemperature = 23, occupiedCoolingSetpoint = 25, minCoolSetpointLimit = 0, maxCoolSetpointLimit = 50) {
|
|
815
|
-
this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Cooling), {
|
|
821
|
+
createDefaultCoolingThermostatClusterServer(localTemperature = 23, occupiedCoolingSetpoint = 25, minCoolSetpointLimit = 0, maxCoolSetpointLimit = 50, unoccupiedCoolingSetpoint = undefined, occupied = undefined, outdoorTemperature = undefined) {
|
|
822
|
+
this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Cooling, ...(occupied !== undefined ? [Thermostat.Feature.Occupancy] : [])), {
|
|
816
823
|
localTemperature: localTemperature * 100,
|
|
824
|
+
...(outdoorTemperature !== undefined ? { outdoorTemperature: outdoorTemperature !== null ? outdoorTemperature * 100 : outdoorTemperature } : {}),
|
|
817
825
|
systemMode: Thermostat.SystemMode.Cool,
|
|
818
826
|
controlSequenceOfOperation: Thermostat.ControlSequenceOfOperation.CoolingOnly,
|
|
819
827
|
occupiedCoolingSetpoint: occupiedCoolingSetpoint * 100,
|
|
@@ -821,6 +829,8 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
821
829
|
maxCoolSetpointLimit: maxCoolSetpointLimit * 100,
|
|
822
830
|
absMinCoolSetpointLimit: minCoolSetpointLimit * 100,
|
|
823
831
|
absMaxCoolSetpointLimit: maxCoolSetpointLimit * 100,
|
|
832
|
+
...(occupied !== undefined ? { unoccupiedCoolingSetpoint: unoccupiedCoolingSetpoint !== undefined ? unoccupiedCoolingSetpoint * 100 : 2700 } : {}),
|
|
833
|
+
...(occupied !== undefined ? { occupancy: { occupied } } : {}),
|
|
824
834
|
});
|
|
825
835
|
return this;
|
|
826
836
|
}
|
package/dist/utils/spawn.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasParameter } from './commandLine.js';
|
|
2
|
-
export async function spawnCommand(matterbridge, command, args) {
|
|
2
|
+
export async function spawnCommand(matterbridge, command, args, packageName) {
|
|
3
3
|
const { spawn } = await import('node:child_process');
|
|
4
4
|
const cmdLine = command + ' ' + args.join(' ');
|
|
5
5
|
if (process.platform === 'win32' && command === 'npm') {
|
|
@@ -13,6 +13,7 @@ export async function spawnCommand(matterbridge, command, args) {
|
|
|
13
13
|
}
|
|
14
14
|
matterbridge.log.debug(`Spawn command ${command} with ${args.join(' ')}`);
|
|
15
15
|
return new Promise((resolve, reject) => {
|
|
16
|
+
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn-init', packageName || `unknown-package`);
|
|
16
17
|
const childProcess = spawn(command, args, {
|
|
17
18
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
18
19
|
});
|
|
@@ -22,6 +23,7 @@ export async function spawnCommand(matterbridge, command, args) {
|
|
|
22
23
|
});
|
|
23
24
|
childProcess.on('close', (code, signal) => {
|
|
24
25
|
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process closed with code ${code} and signal ${signal}`);
|
|
26
|
+
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn-exit', 'Child process closed');
|
|
25
27
|
if (code === 0) {
|
|
26
28
|
if (cmdLine.startsWith('npm install -g'))
|
|
27
29
|
matterbridge.log.notice(`Package ${cmdLine.replace('npm install -g ', '').replace('--verbose', '').replace('--omit=dev', '')} installed correctly`);
|
|
@@ -35,6 +37,7 @@ export async function spawnCommand(matterbridge, command, args) {
|
|
|
35
37
|
});
|
|
36
38
|
childProcess.on('exit', (code, signal) => {
|
|
37
39
|
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn', `child process exited with code ${code} and signal ${signal}`);
|
|
40
|
+
matterbridge.frontend.wssSendLogMessage('spawn', matterbridge.log.now(), 'Matterbridge:spawn-exit', 'Child process exited');
|
|
38
41
|
if (code === 0) {
|
|
39
42
|
matterbridge.log.debug(`Child process "${cmdLine}" exited with code ${code} and signal ${signal}`);
|
|
40
43
|
resolve(true);
|