matterbridge 2.2.4 → 2.2.5-dev.3
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 +24 -0
- package/dist/cli.js +2 -37
- package/dist/cluster/export.js +0 -2
- package/dist/defaultConfigSchema.js +0 -23
- package/dist/deviceManager.js +1 -94
- package/dist/frontend.js +70 -334
- package/dist/index.js +1 -28
- package/dist/logger/export.js +0 -1
- package/dist/matter/behaviors.js +0 -2
- package/dist/matter/clusters.js +0 -2
- package/dist/matter/devices.js +0 -2
- package/dist/matter/endpoints.js +0 -2
- package/dist/matter/export.js +0 -2
- package/dist/matter/types.js +0 -2
- package/dist/matterbridge.js +46 -743
- package/dist/matterbridgeAccessoryPlatform.js +0 -33
- package/dist/matterbridgeBehaviors.js +1 -32
- package/dist/matterbridgeDeviceTypes.js +11 -112
- package/dist/matterbridgeDynamicPlatform.js +0 -33
- package/dist/matterbridgeEndpoint.js +6 -690
- package/dist/matterbridgeEndpointHelpers.js +9 -118
- package/dist/matterbridgePlatform.js +13 -185
- package/dist/matterbridgeTypes.js +0 -24
- package/dist/pluginManager.js +7 -230
- package/dist/shelly.js +6 -121
- package/dist/storage/export.js +0 -1
- package/dist/update.js +0 -45
- package/dist/utils/colorUtils.js +2 -205
- package/dist/utils/copyDirectory.js +1 -37
- package/dist/utils/createZip.js +2 -42
- package/dist/utils/deepCopy.js +0 -40
- package/dist/utils/deepEqual.js +1 -65
- package/dist/utils/export.js +0 -1
- package/dist/utils/isvalid.js +0 -86
- package/dist/utils/network.js +5 -77
- package/dist/utils/parameter.js +0 -41
- package/dist/utils/wait.js +5 -48
- package/frontend/build/asset-manifest.json +80 -64
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/main.ea7910e9.css +2 -0
- package/frontend/build/static/css/main.ea7910e9.css.map +1 -0
- package/frontend/build/static/js/453.d855a71b.chunk.js +2 -0
- package/frontend/build/static/js/{453.abd36b29.chunk.js.map → 453.d855a71b.chunk.js.map} +1 -1
- package/frontend/build/static/js/main.b42b0a2a.js +115 -0
- package/frontend/build/static/js/{main.4a12038d.js.LICENSE.txt → main.b42b0a2a.js.LICENSE.txt} +12 -27
- package/frontend/build/static/js/{main.4a12038d.js.map → main.b42b0a2a.js.map} +1 -1
- package/frontend/build/static/media/roboto-cyrillic-300-normal.44340549d94d10899346.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-300-normal.89d0351bce4bc857dba6.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.86d5c52f4588f9f221d7.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.d67ac585bb6a05dbf71c.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.1fb2c6d685bfb888cfa3.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.36f79cc7e73a69da4438.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.e00802373a2c2db6b30d.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.fd3dfdd6cb1a9175b63d.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.a80c0d0719b1acb8f731.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.b9d87b04a9119d8d2fdf.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.31476620b88eec076438.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5e3f232f89080810567d.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.634ee2238bf30f362d52.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.d6c661248da2fde17768.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.361cdfd3a3f9c4bb09ca.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.6b08bc756cd72f5af9e8.woff +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.8300b541aa89b8301a6f.woff +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.fdd1f928a606aa116a44.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.98a717d5a38e77c0f657.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.ecd8572d631f20ff5bd5.woff +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.4fe733bc436afc295c24.woff +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.5c8100481d4e784afbf2.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.d23e03cf87ba44e5af6f.woff +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.d7dfd0b02cd8311e2a97.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.60729cafbded24073dfb.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.a88b77bb10633a8045e3.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.2d5875b032a1cca91eb2.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.a0baf7d6726d8f751a27.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.1964239c2800b6bd7e39.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.bef9c15c7164d6435aad.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.1aff9f4cd71608489b9a.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.eb28a447335ba6d54fcb.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.cb14f8e80cc69ddbac34.woff +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.db56943a88e4852343ae.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.50a0a61e29c19a2f05cb.woff +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.df1be0be92f6f19b8115.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.599f66a60bdf974e578e.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.c320def131b39bceabd8.woff +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.bcfbe8accc968a375a8e.woff +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.c4d6cab43bec89049809.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.6ddd1cfdbc5e74bcdab8.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.948c05192b1e64d931b1.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.0f86a30ca7e981fcfc99.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.2bfbba2d51a85c8702dd.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.8f02573e78730021ef49.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.aecaab4c4da2bf91377a.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.2d3c3ba6fe2d9c1026a5.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.8e656eff240311c6050a.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-300-normal.90364ecfad5101ceb1a0.woff +0 -0
- package/frontend/build/static/media/roboto-math-300-normal.acc9c7c1d1fe3a1c7d44.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-400-normal.3d3a272e5233c5fb1969.woff +0 -0
- package/frontend/build/static/media/roboto-math-400-normal.b60d9fba1e21da7497e6.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-500-normal.41db483cb764343fca71.woff2 +0 -0
- package/frontend/build/static/media/roboto-math-500-normal.c3014a611cd9d8fa6252.woff +0 -0
- package/frontend/build/static/media/roboto-math-700-normal.a6fde3ddcb1629fd58b7.woff +0 -0
- package/frontend/build/static/media/roboto-math-700-normal.f6f4b54add6ab9d60a0f.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-300-normal.52cdf8344b378f0c4580.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-300-normal.616638ec44336b3da884.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-400-normal.bb5b5d1459beb07bd3d5.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-400-normal.f4f7e3bd8264f1a640cb.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-500-normal.09b674875029289fd9a7.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-500-normal.a5457b0ec984fd4cc8da.woff2 +0 -0
- package/frontend/build/static/media/roboto-symbols-700-normal.017e476ef02f62144169.woff +0 -0
- package/frontend/build/static/media/roboto-symbols-700-normal.634070e045ac99822c21.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.53f399e4522b647bafa7.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.6f0bf63e956c09377ef8.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.1cffe58e71a9109191a2.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.b1b8baa94fbcaa57d098.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.148734d63bd96c6e964f.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.72dbf2a25dd55b80b137.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.44a103f706f3ffe6a041.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.fa58a041a3336692af1e.woff +0 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -2
- package/dist/cli.d.ts +0 -29
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cluster/export.d.ts +0 -2
- package/dist/cluster/export.d.ts.map +0 -1
- package/dist/cluster/export.js.map +0 -1
- package/dist/defaultConfigSchema.d.ts +0 -27
- package/dist/defaultConfigSchema.d.ts.map +0 -1
- package/dist/defaultConfigSchema.js.map +0 -1
- package/dist/deviceManager.d.ts +0 -114
- package/dist/deviceManager.d.ts.map +0 -1
- package/dist/deviceManager.js.map +0 -1
- package/dist/frontend.d.ts +0 -221
- package/dist/frontend.d.ts.map +0 -1
- package/dist/frontend.js.map +0 -1
- package/dist/index.d.ts +0 -35
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/logger/export.d.ts +0 -2
- package/dist/logger/export.d.ts.map +0 -1
- package/dist/logger/export.js.map +0 -1
- package/dist/matter/behaviors.d.ts +0 -2
- package/dist/matter/behaviors.d.ts.map +0 -1
- package/dist/matter/behaviors.js.map +0 -1
- package/dist/matter/clusters.d.ts +0 -2
- package/dist/matter/clusters.d.ts.map +0 -1
- package/dist/matter/clusters.js.map +0 -1
- package/dist/matter/devices.d.ts +0 -2
- package/dist/matter/devices.d.ts.map +0 -1
- package/dist/matter/devices.js.map +0 -1
- package/dist/matter/endpoints.d.ts +0 -2
- package/dist/matter/endpoints.d.ts.map +0 -1
- package/dist/matter/endpoints.js.map +0 -1
- package/dist/matter/export.d.ts +0 -5
- package/dist/matter/export.d.ts.map +0 -1
- package/dist/matter/export.js.map +0 -1
- package/dist/matter/types.d.ts +0 -3
- package/dist/matter/types.d.ts.map +0 -1
- package/dist/matter/types.js.map +0 -1
- package/dist/matterbridge.d.ts +0 -422
- package/dist/matterbridge.d.ts.map +0 -1
- package/dist/matterbridge.js.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
- package/dist/matterbridgeBehaviors.d.ts +0 -1056
- package/dist/matterbridgeBehaviors.d.ts.map +0 -1
- package/dist/matterbridgeBehaviors.js.map +0 -1
- package/dist/matterbridgeDeviceTypes.d.ts +0 -177
- package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
- package/dist/matterbridgeDeviceTypes.js.map +0 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
- package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
- package/dist/matterbridgeDynamicPlatform.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts +0 -835
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgeEndpointHelpers.d.ts +0 -2275
- package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
- package/dist/matterbridgeEndpointHelpers.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts +0 -251
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts +0 -178
- package/dist/matterbridgeTypes.d.ts.map +0 -1
- package/dist/matterbridgeTypes.js.map +0 -1
- package/dist/pluginManager.d.ts +0 -236
- package/dist/pluginManager.d.ts.map +0 -1
- package/dist/pluginManager.js.map +0 -1
- package/dist/shelly.d.ts +0 -77
- package/dist/shelly.d.ts.map +0 -1
- package/dist/shelly.js.map +0 -1
- package/dist/storage/export.d.ts +0 -2
- package/dist/storage/export.d.ts.map +0 -1
- package/dist/storage/export.js.map +0 -1
- package/dist/update.d.ts +0 -32
- package/dist/update.d.ts.map +0 -1
- package/dist/update.js.map +0 -1
- package/dist/utils/colorUtils.d.ts +0 -61
- package/dist/utils/colorUtils.d.ts.map +0 -1
- package/dist/utils/colorUtils.js.map +0 -1
- package/dist/utils/copyDirectory.d.ts +0 -32
- package/dist/utils/copyDirectory.d.ts.map +0 -1
- package/dist/utils/copyDirectory.js.map +0 -1
- package/dist/utils/createZip.d.ts +0 -38
- package/dist/utils/createZip.d.ts.map +0 -1
- package/dist/utils/createZip.js.map +0 -1
- package/dist/utils/deepCopy.d.ts +0 -31
- package/dist/utils/deepCopy.d.ts.map +0 -1
- package/dist/utils/deepCopy.js.map +0 -1
- package/dist/utils/deepEqual.d.ts +0 -53
- package/dist/utils/deepEqual.d.ts.map +0 -1
- package/dist/utils/deepEqual.js.map +0 -1
- package/dist/utils/export.d.ts +0 -10
- package/dist/utils/export.d.ts.map +0 -1
- package/dist/utils/export.js.map +0 -1
- package/dist/utils/isvalid.d.ts +0 -87
- package/dist/utils/isvalid.d.ts.map +0 -1
- package/dist/utils/isvalid.js.map +0 -1
- package/dist/utils/network.d.ts +0 -70
- package/dist/utils/network.d.ts.map +0 -1
- package/dist/utils/network.js.map +0 -1
- package/dist/utils/parameter.d.ts +0 -44
- package/dist/utils/parameter.d.ts.map +0 -1
- package/dist/utils/parameter.js.map +0 -1
- package/dist/utils/wait.d.ts +0 -43
- package/dist/utils/wait.d.ts.map +0 -1
- package/dist/utils/wait.js.map +0 -1
- package/frontend/build/static/css/main.e52977d6.css +0 -2
- package/frontend/build/static/css/main.e52977d6.css.map +0 -1
- package/frontend/build/static/js/453.abd36b29.chunk.js +0 -2
- package/frontend/build/static/js/main.4a12038d.js +0 -115
- package/frontend/build/static/media/roboto-cyrillic-300-normal.1b79538ccd585c259996.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-300-normal.5f077fd7b977d1715acf.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.5d2930082227d172f62c.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-400-normal.a9e19870cf6c4b973427.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.0ae2428323939af5e1ad.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-500-normal.dd7bc8a52c6c70c5a3f5.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.3f6e1548bd5175a8c342.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-700-normal.4fdfc29a10e7d4b7c527.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.795dbc8140e3fef82983.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.80947a31d23c70204b47.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.135d076fa32aa0b4d105.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5cec61a21cc20180fbe1.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.6de16332fda843a3dc3d.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.c0a0638f90b31d6454ba.woff +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.4750292c47fa2bc6ac1a.woff2 +0 -0
- package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.ca247189fc12d00de361.woff +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.285f3e6261d8eb20417d.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-300-normal.889beddda1c9bd9f97df.woff +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.160a791a8e4f46bca3cc.woff +0 -0
- package/frontend/build/static/media/roboto-greek-400-normal.2c32b1315be61477013a.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.60810e07c7b0273013aa.woff +0 -0
- package/frontend/build/static/media/roboto-greek-500-normal.f95e757c5483310f9c11.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.77dd370f2001e184ba0d.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-700-normal.df87b053fae3d7ad5f7a.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.b590dbe5c639944366d1.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-300-normal.d6049cb54aa6fbe14c42.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.16eb83b4a3b1ea994243.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-400-normal.1df4abad55796d11a0c8.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.4a96ba31abcce0f5d52b.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-500-normal.fd28d9c008bf3af1bed7.woff +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.2dd6febad11502dec6a6.woff2 +0 -0
- package/frontend/build/static/media/roboto-greek-ext-700-normal.4abdc9fff4507f17d726.woff +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.b850f1ff581ea232fac9.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-300-normal.c4bc0593c9954d79cb3a.woff +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.047a7839f69b209db815.woff +0 -0
- package/frontend/build/static/media/roboto-latin-400-normal.297d48e1b5a10c0831a9.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.68d40d6d01c6f85d24ba.woff +0 -0
- package/frontend/build/static/media/roboto-latin-500-normal.7077203b1982951ecf76.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.4535474e1cf8598695ad.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-700-normal.9f6a16a7770c87b2042b.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.14982a9e4857a93b6dce.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-300-normal.97cbc447d4a8d41a9543.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.27da5b36b6d3a16f53f4.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-400-normal.2eeae187764baf05867d.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.06c30711d588145a4541.woff +0 -0
- package/frontend/build/static/media/roboto-latin-ext-500-normal.9a18d7bb9ff7a6af7b32.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.18841836e391d39e83a8.woff2 +0 -0
- package/frontend/build/static/media/roboto-latin-ext-700-normal.3c5bcdd0e69c4c3ffafe.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.c96b16e5c05c7b7c3e89.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-300-normal.f5e7cea32756dfe7af40.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.0dc97c66f9b542d6fa17.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-400-normal.d3f8e26d6c27de8102b6.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.090fabef926bdc0e9b9f.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-500-normal.23b7b8a2524d2d4b637b.woff +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.0a79a9fabfc32e33f360.woff2 +0 -0
- package/frontend/build/static/media/roboto-vietnamese-700-normal.35ed0597568ff6f19c16.woff +0 -0
package/dist/frontend.js
CHANGED
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file contains the class Frontend.
|
|
3
|
-
*
|
|
4
|
-
* @file frontend.ts
|
|
5
|
-
* @author Luca Liguori
|
|
6
|
-
* @date 2025-01-13
|
|
7
|
-
* @version 1.0.2
|
|
8
|
-
*
|
|
9
|
-
* Copyright 2025, 2026, 2027 Luca Liguori.
|
|
10
|
-
*
|
|
11
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
-
* you may not use this file except in compliance with the License.
|
|
13
|
-
* You may obtain a copy of the License at
|
|
14
|
-
*
|
|
15
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
-
*
|
|
17
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
-
* See the License for the specific language governing permissions and
|
|
21
|
-
* limitations under the License. *
|
|
22
|
-
*/
|
|
23
|
-
// @matter
|
|
24
1
|
import { EndpointServer, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, Lifecycle } from '@matter/main';
|
|
25
|
-
// Node modules
|
|
26
2
|
import { createServer } from 'node:http';
|
|
27
3
|
import os from 'node:os';
|
|
28
4
|
import path from 'node:path';
|
|
@@ -31,75 +7,21 @@ import https from 'https';
|
|
|
31
7
|
import express from 'express';
|
|
32
8
|
import WebSocket, { WebSocketServer } from 'ws';
|
|
33
9
|
import multer from 'multer';
|
|
34
|
-
|
|
35
|
-
import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
|
|
36
|
-
// Matterbridge
|
|
10
|
+
import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW, nt } from './logger/export.js';
|
|
37
11
|
import { createZip, deepCopy, isValidArray, isValidNumber, isValidObject, isValidString } from './utils/export.js';
|
|
38
12
|
import { plg } from './matterbridgeTypes.js';
|
|
39
13
|
import { hasParameter } from './utils/export.js';
|
|
40
14
|
import { BridgedDeviceBasicInformation } from '@matter/main/clusters';
|
|
41
|
-
/**
|
|
42
|
-
* Websocket message ID for logging.
|
|
43
|
-
* @constant {number}
|
|
44
|
-
*/
|
|
45
15
|
export const WS_ID_LOG = 0;
|
|
46
|
-
/**
|
|
47
|
-
* Websocket message ID indicating a refresh is needed.
|
|
48
|
-
* @constant {number}
|
|
49
|
-
*/
|
|
50
16
|
export const WS_ID_REFRESH_NEEDED = 1;
|
|
51
|
-
/**
|
|
52
|
-
* Websocket message ID indicating a restart is needed.
|
|
53
|
-
* @constant {number}
|
|
54
|
-
*/
|
|
55
17
|
export const WS_ID_RESTART_NEEDED = 2;
|
|
56
|
-
/**
|
|
57
|
-
* Websocket message ID indicating a cpu update.
|
|
58
|
-
* @constant {number}
|
|
59
|
-
*/
|
|
60
18
|
export const WS_ID_CPU_UPDATE = 3;
|
|
61
|
-
/**
|
|
62
|
-
* Websocket message ID indicating a memory update.
|
|
63
|
-
* @constant {number}
|
|
64
|
-
*/
|
|
65
19
|
export const WS_ID_MEMORY_UPDATE = 4;
|
|
66
|
-
/**
|
|
67
|
-
* Websocket message ID indicating an uptime update.
|
|
68
|
-
* @constant {number}
|
|
69
|
-
*/
|
|
70
20
|
export const WS_ID_UPTIME_UPDATE = 5;
|
|
71
|
-
/**
|
|
72
|
-
* Websocket message ID indicating a snackbar message.
|
|
73
|
-
* @constant {number}
|
|
74
|
-
*/
|
|
75
21
|
export const WS_ID_SNACKBAR = 6;
|
|
76
|
-
/**
|
|
77
|
-
* Websocket message ID indicating matterbridge has un update available.
|
|
78
|
-
* @constant {number}
|
|
79
|
-
*/
|
|
80
22
|
export const WS_ID_UPDATE_NEEDED = 7;
|
|
81
|
-
/**
|
|
82
|
-
* Websocket message ID indicating a state update.
|
|
83
|
-
* @constant {number}
|
|
84
|
-
*/
|
|
85
23
|
export const WS_ID_STATEUPDATE = 8;
|
|
86
|
-
/**
|
|
87
|
-
* Websocket message ID indicating a shelly system update.
|
|
88
|
-
* check:
|
|
89
|
-
* curl -k http://127.0.0.1:8101/api/updates/sys/check
|
|
90
|
-
* perform:
|
|
91
|
-
* curl -k http://127.0.0.1:8101/api/updates/sys/perform
|
|
92
|
-
* @constant {number}
|
|
93
|
-
*/
|
|
94
24
|
export const WS_ID_SHELLY_SYS_UPDATE = 100;
|
|
95
|
-
/**
|
|
96
|
-
* Websocket message ID indicating a shelly main update.
|
|
97
|
-
* check:
|
|
98
|
-
* curl -k http://127.0.0.1:8101/api/updates/main/check
|
|
99
|
-
* perform:
|
|
100
|
-
* curl -k http://127.0.0.1:8101/api/updates/main/perform
|
|
101
|
-
* @constant {number}
|
|
102
|
-
*/
|
|
103
25
|
export const WS_ID_SHELLY_MAIN_UPDATE = 101;
|
|
104
26
|
export class Frontend {
|
|
105
27
|
matterbridge;
|
|
@@ -117,7 +39,7 @@ export class Frontend {
|
|
|
117
39
|
memoryTimeout;
|
|
118
40
|
constructor(matterbridge) {
|
|
119
41
|
this.matterbridge = matterbridge;
|
|
120
|
-
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4
|
|
42
|
+
this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
121
43
|
}
|
|
122
44
|
set logLevel(logLevel) {
|
|
123
45
|
this.log.logLevel = logLevel;
|
|
@@ -125,25 +47,13 @@ export class Frontend {
|
|
|
125
47
|
async start(port = 8283) {
|
|
126
48
|
this.port = port;
|
|
127
49
|
this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
|
|
128
|
-
// Initialize multer with the upload directory
|
|
129
50
|
const uploadDir = path.join(this.matterbridge.matterbridgeDirectory, 'uploads');
|
|
130
51
|
await fs.mkdir(uploadDir, { recursive: true });
|
|
131
52
|
const upload = multer({ dest: uploadDir });
|
|
132
|
-
// Create the express app that serves the frontend
|
|
133
53
|
this.expressApp = express();
|
|
134
|
-
// Log all requests to the server for debugging
|
|
135
|
-
/*
|
|
136
|
-
this.expressApp.use((req, res, next) => {
|
|
137
|
-
this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
|
|
138
|
-
next();
|
|
139
|
-
});
|
|
140
|
-
*/
|
|
141
|
-
// Serve static files from '/static' endpoint
|
|
142
54
|
this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
|
|
143
55
|
if (!hasParameter('ssl')) {
|
|
144
|
-
// Create an HTTP server and attach the express app
|
|
145
56
|
this.httpServer = createServer(this.expressApp);
|
|
146
|
-
// Listen on the specified port
|
|
147
57
|
if (hasParameter('ingress')) {
|
|
148
58
|
this.httpServer.listen(this.port, '0.0.0.0', () => {
|
|
149
59
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -157,7 +67,6 @@ export class Frontend {
|
|
|
157
67
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
158
68
|
});
|
|
159
69
|
}
|
|
160
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
70
|
this.httpServer.on('error', (error) => {
|
|
162
71
|
this.log.error(`Frontend http server error listening on ${this.port}`);
|
|
163
72
|
switch (error.code) {
|
|
@@ -173,7 +82,6 @@ export class Frontend {
|
|
|
173
82
|
});
|
|
174
83
|
}
|
|
175
84
|
else {
|
|
176
|
-
// Load the SSL certificate, the private key and optionally the CA certificate
|
|
177
85
|
let cert;
|
|
178
86
|
try {
|
|
179
87
|
cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
|
|
@@ -201,9 +109,7 @@ export class Frontend {
|
|
|
201
109
|
this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
|
|
202
110
|
}
|
|
203
111
|
const serverOptions = { cert, key, ca };
|
|
204
|
-
// Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
|
|
205
112
|
this.httpsServer = https.createServer(serverOptions, this.expressApp);
|
|
206
|
-
// Listen on the specified port
|
|
207
113
|
if (hasParameter('ingress')) {
|
|
208
114
|
this.httpsServer.listen(this.port, '0.0.0.0', () => {
|
|
209
115
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -217,7 +123,6 @@ export class Frontend {
|
|
|
217
123
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
218
124
|
});
|
|
219
125
|
}
|
|
220
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
221
126
|
this.httpsServer.on('error', (error) => {
|
|
222
127
|
this.log.error(`Frontend https server error listening on ${this.port}`);
|
|
223
128
|
switch (error.code) {
|
|
@@ -234,18 +139,16 @@ export class Frontend {
|
|
|
234
139
|
}
|
|
235
140
|
if (this.initializeError)
|
|
236
141
|
return;
|
|
237
|
-
// Create a WebSocket server and attach it to the http or https server
|
|
238
142
|
const wssPort = this.port;
|
|
239
143
|
const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
|
|
240
144
|
this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
|
|
241
145
|
this.webSocketServer.on('connection', (ws, request) => {
|
|
242
146
|
const clientIp = request.socket.remoteAddress;
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
callbackLogLevel = "debug" /* LogLevel.DEBUG */;
|
|
147
|
+
let callbackLogLevel = "notice";
|
|
148
|
+
if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
|
|
149
|
+
callbackLogLevel = "info";
|
|
150
|
+
if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
|
|
151
|
+
callbackLogLevel = "debug";
|
|
249
152
|
AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), callbackLogLevel);
|
|
250
153
|
this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
|
|
251
154
|
this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
|
|
@@ -279,7 +182,6 @@ export class Frontend {
|
|
|
279
182
|
this.webSocketServer.on('error', (ws, error) => {
|
|
280
183
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
281
184
|
});
|
|
282
|
-
// Subscribe to cli events
|
|
283
185
|
const { cliEmitter } = await import('./cli.js');
|
|
284
186
|
cliEmitter.removeAllListeners();
|
|
285
187
|
cliEmitter.on('uptime', (systemUptime, processUptime) => {
|
|
@@ -291,7 +193,6 @@ export class Frontend {
|
|
|
291
193
|
cliEmitter.on('cpu', (cpuUsage) => {
|
|
292
194
|
this.wssSendCpuUpdate(cpuUsage);
|
|
293
195
|
});
|
|
294
|
-
// Endpoint to validate login code
|
|
295
196
|
this.expressApp.post('/api/login', express.json(), async (req, res) => {
|
|
296
197
|
const { password } = req.body;
|
|
297
198
|
this.log.debug('The frontend sent /api/login', password);
|
|
@@ -310,27 +211,23 @@ export class Frontend {
|
|
|
310
211
|
this.log.warn('/api/login error wrong password');
|
|
311
212
|
res.json({ valid: false });
|
|
312
213
|
}
|
|
313
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
314
214
|
}
|
|
315
215
|
catch (error) {
|
|
316
216
|
this.log.error('/api/login error getting password');
|
|
317
217
|
res.json({ valid: false });
|
|
318
218
|
}
|
|
319
219
|
});
|
|
320
|
-
// Endpoint to provide health check
|
|
321
220
|
this.expressApp.get('/health', (req, res) => {
|
|
322
221
|
this.log.debug('Express received /health');
|
|
323
222
|
const healthStatus = {
|
|
324
|
-
status: 'ok',
|
|
325
|
-
uptime: process.uptime(),
|
|
326
|
-
timestamp: new Date().toISOString(),
|
|
223
|
+
status: 'ok',
|
|
224
|
+
uptime: process.uptime(),
|
|
225
|
+
timestamp: new Date().toISOString(),
|
|
327
226
|
};
|
|
328
227
|
res.status(200).json(healthStatus);
|
|
329
228
|
});
|
|
330
|
-
// Endpoint to provide memory usage details
|
|
331
229
|
this.expressApp.get('/memory', async (req, res) => {
|
|
332
230
|
this.log.debug('Express received /memory');
|
|
333
|
-
// Memory usage from process
|
|
334
231
|
const memoryUsageRaw = process.memoryUsage();
|
|
335
232
|
const memoryUsage = {
|
|
336
233
|
rss: this.formatMemoryUsage(memoryUsageRaw.rss),
|
|
@@ -339,13 +236,10 @@ export class Frontend {
|
|
|
339
236
|
external: this.formatMemoryUsage(memoryUsageRaw.external),
|
|
340
237
|
arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
|
|
341
238
|
};
|
|
342
|
-
// V8 heap statistics
|
|
343
239
|
const { default: v8 } = await import('node:v8');
|
|
344
240
|
const heapStatsRaw = v8.getHeapStatistics();
|
|
345
241
|
const heapSpacesRaw = v8.getHeapSpaceStatistics();
|
|
346
|
-
// Format heapStats
|
|
347
242
|
const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
|
|
348
|
-
// Format heapSpaces
|
|
349
243
|
const heapSpaces = heapSpacesRaw.map((space) => ({
|
|
350
244
|
...space,
|
|
351
245
|
space_size: this.formatMemoryUsage(space.space_size),
|
|
@@ -363,7 +257,6 @@ export class Frontend {
|
|
|
363
257
|
};
|
|
364
258
|
res.status(200).json(memoryReport);
|
|
365
259
|
});
|
|
366
|
-
// Endpoint to start advertising the server node
|
|
367
260
|
this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
|
|
368
261
|
const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
|
|
369
262
|
if (pairingCodes) {
|
|
@@ -374,22 +267,18 @@ export class Frontend {
|
|
|
374
267
|
res.status(500).json({ error: 'Failed to generate pairing codes' });
|
|
375
268
|
}
|
|
376
269
|
});
|
|
377
|
-
// Endpoint to provide settings
|
|
378
270
|
this.expressApp.get('/api/settings', express.json(), async (req, res) => {
|
|
379
271
|
this.log.debug('The frontend sent /api/settings');
|
|
380
272
|
res.json(await this.getApiSettings());
|
|
381
273
|
});
|
|
382
|
-
// Endpoint to provide plugins
|
|
383
274
|
this.expressApp.get('/api/plugins', async (req, res) => {
|
|
384
275
|
this.log.debug('The frontend sent /api/plugins');
|
|
385
276
|
res.json(this.getBaseRegisteredPlugins());
|
|
386
277
|
});
|
|
387
|
-
// Endpoint to provide devices
|
|
388
278
|
this.expressApp.get('/api/devices', (req, res) => {
|
|
389
279
|
this.log.debug('The frontend sent /api/devices');
|
|
390
280
|
const devices = [];
|
|
391
281
|
this.matterbridge.devices.forEach(async (device) => {
|
|
392
|
-
// Check if the device has the required properties
|
|
393
282
|
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
394
283
|
return;
|
|
395
284
|
const cluster = this.getClusterTextFromDevice(device);
|
|
@@ -408,7 +297,6 @@ export class Frontend {
|
|
|
408
297
|
});
|
|
409
298
|
res.json(devices);
|
|
410
299
|
});
|
|
411
|
-
// Endpoint to provide the cluster servers of the devices
|
|
412
300
|
this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
|
|
413
301
|
const selectedPluginName = req.params.selectedPluginName;
|
|
414
302
|
const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
|
|
@@ -481,7 +369,6 @@ export class Frontend {
|
|
|
481
369
|
});
|
|
482
370
|
res.json(data);
|
|
483
371
|
});
|
|
484
|
-
// Endpoint to view the log
|
|
485
372
|
this.expressApp.get('/api/view-log', async (req, res) => {
|
|
486
373
|
this.log.debug('The frontend sent /api/log');
|
|
487
374
|
try {
|
|
@@ -494,12 +381,10 @@ export class Frontend {
|
|
|
494
381
|
res.status(500).send('Error reading log file');
|
|
495
382
|
}
|
|
496
383
|
});
|
|
497
|
-
// Endpoint to download the matterbridge log
|
|
498
384
|
this.expressApp.get('/api/download-mblog', async (req, res) => {
|
|
499
385
|
this.log.debug('The frontend sent /api/download-mblog');
|
|
500
386
|
try {
|
|
501
387
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
|
|
502
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
503
388
|
}
|
|
504
389
|
catch (error) {
|
|
505
390
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -511,12 +396,10 @@ export class Frontend {
|
|
|
511
396
|
}
|
|
512
397
|
});
|
|
513
398
|
});
|
|
514
|
-
// Endpoint to download the matter log
|
|
515
399
|
this.expressApp.get('/api/download-mjlog', async (req, res) => {
|
|
516
400
|
this.log.debug('The frontend sent /api/download-mjlog');
|
|
517
401
|
try {
|
|
518
402
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
|
|
519
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
520
403
|
}
|
|
521
404
|
catch (error) {
|
|
522
405
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
|
|
@@ -528,12 +411,10 @@ export class Frontend {
|
|
|
528
411
|
}
|
|
529
412
|
});
|
|
530
413
|
});
|
|
531
|
-
// Endpoint to download the matter log
|
|
532
414
|
this.expressApp.get('/api/shellydownloadsystemlog', async (req, res) => {
|
|
533
415
|
this.log.debug('The frontend sent /api/shellydownloadsystemlog');
|
|
534
416
|
try {
|
|
535
417
|
await fs.access(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), fs.constants.F_OK);
|
|
536
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
537
418
|
}
|
|
538
419
|
catch (error) {
|
|
539
420
|
fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), 'Create the Shelly system log before downloading it.');
|
|
@@ -545,7 +426,6 @@ export class Frontend {
|
|
|
545
426
|
}
|
|
546
427
|
});
|
|
547
428
|
});
|
|
548
|
-
// Endpoint to download the matter storage file
|
|
549
429
|
this.expressApp.get('/api/download-mjstorage', async (req, res) => {
|
|
550
430
|
this.log.debug('The frontend sent /api/download-mjstorage');
|
|
551
431
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
|
|
@@ -556,7 +436,6 @@ export class Frontend {
|
|
|
556
436
|
}
|
|
557
437
|
});
|
|
558
438
|
});
|
|
559
|
-
// Endpoint to download the matterbridge storage directory
|
|
560
439
|
this.expressApp.get('/api/download-mbstorage', async (req, res) => {
|
|
561
440
|
this.log.debug('The frontend sent /api/download-mbstorage');
|
|
562
441
|
await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
|
|
@@ -567,7 +446,6 @@ export class Frontend {
|
|
|
567
446
|
}
|
|
568
447
|
});
|
|
569
448
|
});
|
|
570
|
-
// Endpoint to download the matterbridge plugin directory
|
|
571
449
|
this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
|
|
572
450
|
this.log.debug('The frontend sent /api/download-pluginstorage');
|
|
573
451
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
|
|
@@ -578,11 +456,9 @@ export class Frontend {
|
|
|
578
456
|
}
|
|
579
457
|
});
|
|
580
458
|
});
|
|
581
|
-
// Endpoint to download the matterbridge plugin config files
|
|
582
459
|
this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
|
|
583
460
|
this.log.debug('The frontend sent /api/download-pluginconfig');
|
|
584
461
|
await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
|
|
585
|
-
// await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, 'certs', '*.*')), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
|
|
586
462
|
res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
|
|
587
463
|
if (error) {
|
|
588
464
|
this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
|
|
@@ -590,7 +466,6 @@ export class Frontend {
|
|
|
590
466
|
}
|
|
591
467
|
});
|
|
592
468
|
});
|
|
593
|
-
// Endpoint to download the matterbridge plugin config files
|
|
594
469
|
this.expressApp.get('/api/download-backup', async (req, res) => {
|
|
595
470
|
this.log.debug('The frontend sent /api/download-backup');
|
|
596
471
|
res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
|
|
@@ -600,7 +475,6 @@ export class Frontend {
|
|
|
600
475
|
}
|
|
601
476
|
});
|
|
602
477
|
});
|
|
603
|
-
// Endpoint to receive commands
|
|
604
478
|
this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
|
|
605
479
|
const command = req.params.command;
|
|
606
480
|
let param = req.params.param;
|
|
@@ -610,15 +484,13 @@ export class Frontend {
|
|
|
610
484
|
return;
|
|
611
485
|
}
|
|
612
486
|
this.log.debug(`Received frontend command: ${command}:${param}`);
|
|
613
|
-
// Handle the command setpassword from Settings
|
|
614
487
|
if (command === 'setpassword') {
|
|
615
|
-
const password = param.slice(1, -1);
|
|
488
|
+
const password = param.slice(1, -1);
|
|
616
489
|
this.log.debug('setpassword', param, password);
|
|
617
490
|
await this.matterbridge.nodeContext?.set('password', password);
|
|
618
491
|
res.json({ message: 'Command received' });
|
|
619
492
|
return;
|
|
620
493
|
}
|
|
621
|
-
// Handle the command setbridgemode from Settings
|
|
622
494
|
if (command === 'setbridgemode') {
|
|
623
495
|
this.log.debug(`setbridgemode: ${param}`);
|
|
624
496
|
this.wssSendRestartRequired();
|
|
@@ -626,7 +498,6 @@ export class Frontend {
|
|
|
626
498
|
res.json({ message: 'Command received' });
|
|
627
499
|
return;
|
|
628
500
|
}
|
|
629
|
-
// Handle the command backup from Settings
|
|
630
501
|
if (command === 'backup') {
|
|
631
502
|
this.log.notice(`Prepairing the backup...`);
|
|
632
503
|
await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
|
|
@@ -635,33 +506,31 @@ export class Frontend {
|
|
|
635
506
|
res.json({ message: 'Command received' });
|
|
636
507
|
return;
|
|
637
508
|
}
|
|
638
|
-
// Handle the command setmbloglevel from Settings
|
|
639
509
|
if (command === 'setmbloglevel') {
|
|
640
510
|
this.log.debug('Matterbridge log level:', param);
|
|
641
511
|
if (param === 'Debug') {
|
|
642
|
-
this.log.logLevel = "debug"
|
|
512
|
+
this.log.logLevel = "debug";
|
|
643
513
|
}
|
|
644
514
|
else if (param === 'Info') {
|
|
645
|
-
this.log.logLevel = "info"
|
|
515
|
+
this.log.logLevel = "info";
|
|
646
516
|
}
|
|
647
517
|
else if (param === 'Notice') {
|
|
648
|
-
this.log.logLevel = "notice"
|
|
518
|
+
this.log.logLevel = "notice";
|
|
649
519
|
}
|
|
650
520
|
else if (param === 'Warn') {
|
|
651
|
-
this.log.logLevel = "warn"
|
|
521
|
+
this.log.logLevel = "warn";
|
|
652
522
|
}
|
|
653
523
|
else if (param === 'Error') {
|
|
654
|
-
this.log.logLevel = "error"
|
|
524
|
+
this.log.logLevel = "error";
|
|
655
525
|
}
|
|
656
526
|
else if (param === 'Fatal') {
|
|
657
|
-
this.log.logLevel = "fatal"
|
|
527
|
+
this.log.logLevel = "fatal";
|
|
658
528
|
}
|
|
659
529
|
await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
|
|
660
530
|
await this.matterbridge.setLogLevel(this.log.logLevel);
|
|
661
531
|
res.json({ message: 'Command received' });
|
|
662
532
|
return;
|
|
663
533
|
}
|
|
664
|
-
// Handle the command setmbloglevel from Settings
|
|
665
534
|
if (command === 'setmjloglevel') {
|
|
666
535
|
this.log.debug('Matter.js log level:', param);
|
|
667
536
|
if (param === 'Debug') {
|
|
@@ -686,34 +555,30 @@ export class Frontend {
|
|
|
686
555
|
res.json({ message: 'Command received' });
|
|
687
556
|
return;
|
|
688
557
|
}
|
|
689
|
-
// Handle the command setmdnsinterface from Settings
|
|
690
558
|
if (command === 'setmdnsinterface') {
|
|
691
|
-
param = param.slice(1, -1);
|
|
559
|
+
param = param.slice(1, -1);
|
|
692
560
|
this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
|
|
693
561
|
this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
|
|
694
562
|
await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
|
|
695
563
|
res.json({ message: 'Command received' });
|
|
696
564
|
return;
|
|
697
565
|
}
|
|
698
|
-
// Handle the command setipv4address from Settings
|
|
699
566
|
if (command === 'setipv4address') {
|
|
700
|
-
param = param.slice(1, -1);
|
|
567
|
+
param = param.slice(1, -1);
|
|
701
568
|
this.matterbridge.matterbridgeInformation.matteripv4address = param;
|
|
702
569
|
this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
|
|
703
570
|
await this.matterbridge.nodeContext?.set('matteripv4address', param);
|
|
704
571
|
res.json({ message: 'Command received' });
|
|
705
572
|
return;
|
|
706
573
|
}
|
|
707
|
-
// Handle the command setipv6address from Settings
|
|
708
574
|
if (command === 'setipv6address') {
|
|
709
|
-
param = param.slice(1, -1);
|
|
575
|
+
param = param.slice(1, -1);
|
|
710
576
|
this.matterbridge.matterbridgeInformation.matteripv6address = param;
|
|
711
577
|
this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
|
|
712
578
|
await this.matterbridge.nodeContext?.set('matteripv6address', param);
|
|
713
579
|
res.json({ message: 'Command received' });
|
|
714
580
|
return;
|
|
715
581
|
}
|
|
716
|
-
// Handle the command setmatterport from Settings
|
|
717
582
|
if (command === 'setmatterport') {
|
|
718
583
|
const port = Math.min(Math.max(parseInt(param), 5540), 5560);
|
|
719
584
|
this.matterbridge.matterbridgeInformation.matterPort = port;
|
|
@@ -722,7 +587,6 @@ export class Frontend {
|
|
|
722
587
|
res.json({ message: 'Command received' });
|
|
723
588
|
return;
|
|
724
589
|
}
|
|
725
|
-
// Handle the command setmatterdiscriminator from Settings
|
|
726
590
|
if (command === 'setmatterdiscriminator') {
|
|
727
591
|
const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
|
|
728
592
|
this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
|
|
@@ -731,7 +595,6 @@ export class Frontend {
|
|
|
731
595
|
res.json({ message: 'Command received' });
|
|
732
596
|
return;
|
|
733
597
|
}
|
|
734
|
-
// Handle the command setmatterpasscode from Settings
|
|
735
598
|
if (command === 'setmatterpasscode') {
|
|
736
599
|
const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
|
|
737
600
|
this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
|
|
@@ -740,20 +603,17 @@ export class Frontend {
|
|
|
740
603
|
res.json({ message: 'Command received' });
|
|
741
604
|
return;
|
|
742
605
|
}
|
|
743
|
-
// Handle the command setmbloglevel from Settings
|
|
744
606
|
if (command === 'setmblogfile') {
|
|
745
607
|
this.log.debug('Matterbridge file log:', param);
|
|
746
608
|
this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
|
|
747
609
|
await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
|
|
748
|
-
// Create the file logger for matterbridge
|
|
749
610
|
if (param === 'true')
|
|
750
|
-
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug"
|
|
611
|
+
AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
|
|
751
612
|
else
|
|
752
613
|
AnsiLogger.setGlobalLogfile(undefined);
|
|
753
614
|
res.json({ message: 'Command received' });
|
|
754
615
|
return;
|
|
755
616
|
}
|
|
756
|
-
// Handle the command setmbloglevel from Settings
|
|
757
617
|
if (command === 'setmjlogfile') {
|
|
758
618
|
this.log.debug('Matter file log:', param);
|
|
759
619
|
this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
|
|
@@ -780,48 +640,40 @@ export class Frontend {
|
|
|
780
640
|
res.json({ message: 'Command received' });
|
|
781
641
|
return;
|
|
782
642
|
}
|
|
783
|
-
// Handle the command unregister from Settings
|
|
784
643
|
if (command === 'unregister') {
|
|
785
644
|
await this.matterbridge.unregisterAndShutdownProcess();
|
|
786
645
|
res.json({ message: 'Command received' });
|
|
787
646
|
return;
|
|
788
647
|
}
|
|
789
|
-
// Handle the command reset from Settings
|
|
790
648
|
if (command === 'reset') {
|
|
791
649
|
await this.matterbridge.shutdownProcessAndReset();
|
|
792
650
|
res.json({ message: 'Command received' });
|
|
793
651
|
return;
|
|
794
652
|
}
|
|
795
|
-
// Handle the command factoryreset from Settings
|
|
796
653
|
if (command === 'factoryreset') {
|
|
797
654
|
await this.matterbridge.shutdownProcessAndFactoryReset();
|
|
798
655
|
res.json({ message: 'Command received' });
|
|
799
656
|
return;
|
|
800
657
|
}
|
|
801
|
-
// Handle the command shutdown from Header
|
|
802
658
|
if (command === 'shutdown') {
|
|
803
659
|
await this.matterbridge.shutdownProcess();
|
|
804
660
|
res.json({ message: 'Command received' });
|
|
805
661
|
return;
|
|
806
662
|
}
|
|
807
|
-
// Handle the command restart from Header
|
|
808
663
|
if (command === 'restart') {
|
|
809
664
|
await this.matterbridge.restartProcess();
|
|
810
665
|
res.json({ message: 'Command received' });
|
|
811
666
|
return;
|
|
812
667
|
}
|
|
813
|
-
// Handle the command update from Header
|
|
814
668
|
if (command === 'update') {
|
|
815
669
|
await this.matterbridge.updateProcess();
|
|
816
670
|
this.wssSendRestartRequired();
|
|
817
671
|
res.json({ message: 'Command received' });
|
|
818
672
|
return;
|
|
819
673
|
}
|
|
820
|
-
// Handle the command saveconfig from Home
|
|
821
674
|
if (command === 'saveconfig') {
|
|
822
675
|
param = param.replace(/\*/g, '\\');
|
|
823
676
|
this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
|
|
824
|
-
// console.log('Req.body:', JSON.stringify(req.body, null, 2));
|
|
825
677
|
if (!this.matterbridge.plugins.has(param)) {
|
|
826
678
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
827
679
|
}
|
|
@@ -836,7 +688,6 @@ export class Frontend {
|
|
|
836
688
|
res.json({ message: 'Command received' });
|
|
837
689
|
return;
|
|
838
690
|
}
|
|
839
|
-
// Handle the command installplugin from Home
|
|
840
691
|
if (command === 'installplugin') {
|
|
841
692
|
param = param.replace(/\*/g, '\\');
|
|
842
693
|
this.log.info(`Installing plugin ${plg}${param}${nf}...`);
|
|
@@ -845,7 +696,6 @@ export class Frontend {
|
|
|
845
696
|
await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
|
|
846
697
|
this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
|
|
847
698
|
this.wssSendSnackbarMessage(`Installed package ${param}`, 10, 'success');
|
|
848
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
849
699
|
}
|
|
850
700
|
catch (error) {
|
|
851
701
|
this.log.error(`Error installing plugin ${plg}${param}${er}`);
|
|
@@ -853,22 +703,17 @@ export class Frontend {
|
|
|
853
703
|
}
|
|
854
704
|
this.wssSendRestartRequired();
|
|
855
705
|
param = param.split('@')[0];
|
|
856
|
-
// Also add the plugin to matterbridge so no return!
|
|
857
706
|
if (param === 'matterbridge') {
|
|
858
|
-
// If we used the command installplugin to install a dev or a specific version of matterbridge we don't want to add it to matterbridge
|
|
859
707
|
res.json({ message: 'Command received' });
|
|
860
708
|
return;
|
|
861
709
|
}
|
|
862
710
|
}
|
|
863
|
-
// Handle the command addplugin from Home
|
|
864
711
|
if (command === 'addplugin' || command === 'installplugin') {
|
|
865
712
|
param = param.replace(/\*/g, '\\');
|
|
866
713
|
const plugin = await this.matterbridge.plugins.add(param);
|
|
867
714
|
if (plugin) {
|
|
868
715
|
this.wssSendSnackbarMessage(`Added plugin ${param}`);
|
|
869
716
|
if (this.matterbridge.bridgeMode === 'childbridge') {
|
|
870
|
-
// We don't know now if the plugin is a dynamic platform or an accessory platform so we create the server node and the aggregator node
|
|
871
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
872
717
|
this.matterbridge.createDynamicPlugin(plugin, true);
|
|
873
718
|
}
|
|
874
719
|
this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true).then(() => {
|
|
@@ -878,14 +723,13 @@ export class Frontend {
|
|
|
878
723
|
res.json({ message: 'Command received' });
|
|
879
724
|
return;
|
|
880
725
|
}
|
|
881
|
-
// Handle the command removeplugin from Home
|
|
882
726
|
if (command === 'removeplugin') {
|
|
883
727
|
if (!this.matterbridge.plugins.has(param)) {
|
|
884
728
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
885
729
|
}
|
|
886
730
|
else {
|
|
887
731
|
const plugin = this.matterbridge.plugins.get(param);
|
|
888
|
-
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
|
|
732
|
+
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
|
|
889
733
|
await this.matterbridge.plugins.remove(param);
|
|
890
734
|
this.wssSendSnackbarMessage(`Removed plugin ${param}`);
|
|
891
735
|
this.wssSendRefreshRequired('plugins');
|
|
@@ -893,7 +737,6 @@ export class Frontend {
|
|
|
893
737
|
res.json({ message: 'Command received' });
|
|
894
738
|
return;
|
|
895
739
|
}
|
|
896
|
-
// Handle the command enableplugin from Home
|
|
897
740
|
if (command === 'enableplugin') {
|
|
898
741
|
if (!this.matterbridge.plugins.has(param)) {
|
|
899
742
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -912,7 +755,6 @@ export class Frontend {
|
|
|
912
755
|
await this.matterbridge.plugins.enable(param);
|
|
913
756
|
this.wssSendSnackbarMessage(`Enabled plugin ${param}`);
|
|
914
757
|
if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
|
|
915
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
916
758
|
this.matterbridge.createDynamicPlugin(plugin, true);
|
|
917
759
|
}
|
|
918
760
|
this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true).then(() => {
|
|
@@ -923,7 +765,6 @@ export class Frontend {
|
|
|
923
765
|
res.json({ message: 'Command received' });
|
|
924
766
|
return;
|
|
925
767
|
}
|
|
926
|
-
// Handle the command disableplugin from Home
|
|
927
768
|
if (command === 'disableplugin') {
|
|
928
769
|
if (!this.matterbridge.plugins.has(param)) {
|
|
929
770
|
this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
|
|
@@ -931,7 +772,7 @@ export class Frontend {
|
|
|
931
772
|
else {
|
|
932
773
|
const plugin = this.matterbridge.plugins.get(param);
|
|
933
774
|
if (plugin && plugin.enabled) {
|
|
934
|
-
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
775
|
+
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
935
776
|
await this.matterbridge.plugins.disable(param);
|
|
936
777
|
this.wssSendSnackbarMessage(`Disabled plugin ${param}`);
|
|
937
778
|
this.wssSendRefreshRequired('plugins');
|
|
@@ -950,13 +791,10 @@ export class Frontend {
|
|
|
950
791
|
return;
|
|
951
792
|
}
|
|
952
793
|
this.wssSendSnackbarMessage(`Installing package ${filename}. Please wait...`);
|
|
953
|
-
// Define the path where the plugin file will be saved
|
|
954
794
|
const filePath = path.join(this.matterbridge.matterbridgeDirectory, 'uploads', filename);
|
|
955
795
|
try {
|
|
956
|
-
// Move the uploaded file to the specified path
|
|
957
796
|
await fs.rename(file.path, filePath);
|
|
958
797
|
this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
|
|
959
|
-
// Install the plugin package
|
|
960
798
|
if (filename.endsWith('.tgz')) {
|
|
961
799
|
await this.matterbridge.spawnCommand('npm', ['install', '-g', filePath, '--omit=dev', '--verbose']);
|
|
962
800
|
this.log.info(`Plugin package ${plg}${filename}${nf} installed successfully. Full restart required.`);
|
|
@@ -973,7 +811,6 @@ export class Frontend {
|
|
|
973
811
|
res.status(500).send(`Error uploading or installing plugin package ${filename}`);
|
|
974
812
|
}
|
|
975
813
|
});
|
|
976
|
-
// Fallback for routing (must be the last route)
|
|
977
814
|
this.expressApp.get('*', (req, res) => {
|
|
978
815
|
this.log.debug('The frontend sent:', req.url);
|
|
979
816
|
this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
|
|
@@ -982,31 +819,24 @@ export class Frontend {
|
|
|
982
819
|
this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
|
|
983
820
|
}
|
|
984
821
|
async stop() {
|
|
985
|
-
// Remove all listeners from the cliEmitter
|
|
986
|
-
// cliEmitter.removeAllListeners();
|
|
987
|
-
// Close the http server
|
|
988
822
|
if (this.httpServer) {
|
|
989
823
|
this.httpServer.close();
|
|
990
824
|
this.httpServer.removeAllListeners();
|
|
991
825
|
this.httpServer = undefined;
|
|
992
826
|
this.log.debug('Frontend http server closed successfully');
|
|
993
827
|
}
|
|
994
|
-
// Close the https server
|
|
995
828
|
if (this.httpsServer) {
|
|
996
829
|
this.httpsServer.close();
|
|
997
830
|
this.httpsServer.removeAllListeners();
|
|
998
831
|
this.httpsServer = undefined;
|
|
999
832
|
this.log.debug('Frontend https server closed successfully');
|
|
1000
833
|
}
|
|
1001
|
-
// Remove listeners from the express app
|
|
1002
834
|
if (this.expressApp) {
|
|
1003
835
|
this.expressApp.removeAllListeners();
|
|
1004
836
|
this.expressApp = undefined;
|
|
1005
837
|
this.log.debug('Frontend app closed successfully');
|
|
1006
838
|
}
|
|
1007
|
-
// Close the WebSocket server
|
|
1008
839
|
if (this.webSocketServer) {
|
|
1009
|
-
// Close all active connections
|
|
1010
840
|
this.webSocketServer.clients.forEach((client) => {
|
|
1011
841
|
if (client.readyState === WebSocket.OPEN) {
|
|
1012
842
|
client.close();
|
|
@@ -1023,7 +853,6 @@ export class Frontend {
|
|
|
1023
853
|
this.webSocketServer = undefined;
|
|
1024
854
|
}
|
|
1025
855
|
}
|
|
1026
|
-
// Function to format bytes to KB, MB, or GB
|
|
1027
856
|
formatMemoryUsage = (bytes) => {
|
|
1028
857
|
if (bytes >= 1024 ** 3) {
|
|
1029
858
|
return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
|
|
@@ -1035,7 +864,6 @@ export class Frontend {
|
|
|
1035
864
|
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
1036
865
|
}
|
|
1037
866
|
};
|
|
1038
|
-
// Function to format system uptime with only the most significant unit
|
|
1039
867
|
formatOsUpTime = (seconds) => {
|
|
1040
868
|
if (seconds >= 86400) {
|
|
1041
869
|
const days = Math.floor(seconds / 86400);
|
|
@@ -1051,13 +879,8 @@ export class Frontend {
|
|
|
1051
879
|
}
|
|
1052
880
|
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
1053
881
|
};
|
|
1054
|
-
/**
|
|
1055
|
-
* Retrieves the api settings data.
|
|
1056
|
-
* @returns {Promise<object>} A promise that resolve in the api settings object.
|
|
1057
|
-
*/
|
|
1058
882
|
async getApiSettings() {
|
|
1059
883
|
const { lastCpuUsage } = await import('./cli.js');
|
|
1060
|
-
// Update the system information
|
|
1061
884
|
this.matterbridge.systemInformation.totalMemory = this.formatMemoryUsage(os.totalmem());
|
|
1062
885
|
this.matterbridge.systemInformation.freeMemory = this.formatMemoryUsage(os.freemem());
|
|
1063
886
|
this.matterbridge.systemInformation.systemUptime = this.formatOsUpTime(os.uptime());
|
|
@@ -1066,7 +889,6 @@ export class Frontend {
|
|
|
1066
889
|
this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
|
|
1067
890
|
this.matterbridge.systemInformation.heapTotal = this.formatMemoryUsage(process.memoryUsage().heapTotal);
|
|
1068
891
|
this.matterbridge.systemInformation.heapUsed = this.formatMemoryUsage(process.memoryUsage().heapUsed);
|
|
1069
|
-
// Update the matterbridge information
|
|
1070
892
|
this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
|
|
1071
893
|
this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
|
|
1072
894
|
this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
|
|
@@ -1085,11 +907,6 @@ export class Frontend {
|
|
|
1085
907
|
this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
|
|
1086
908
|
return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
|
|
1087
909
|
}
|
|
1088
|
-
/**
|
|
1089
|
-
* Retrieves the reachable attribute.
|
|
1090
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
1091
|
-
* @returns {boolean} The reachable attribute.
|
|
1092
|
-
*/
|
|
1093
910
|
getReachability(device) {
|
|
1094
911
|
if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
|
|
1095
912
|
return false;
|
|
@@ -1099,11 +916,6 @@ export class Frontend {
|
|
|
1099
916
|
return true;
|
|
1100
917
|
return false;
|
|
1101
918
|
}
|
|
1102
|
-
/**
|
|
1103
|
-
* Retrieves the cluster text description from a given device.
|
|
1104
|
-
* @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
|
|
1105
|
-
* @returns {string} The attributes description of the cluster servers in the device.
|
|
1106
|
-
*/
|
|
1107
919
|
getClusterTextFromDevice(device) {
|
|
1108
920
|
if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
|
|
1109
921
|
return '';
|
|
@@ -1144,7 +956,6 @@ export class Frontend {
|
|
|
1144
956
|
};
|
|
1145
957
|
let attributes = '';
|
|
1146
958
|
device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
|
|
1147
|
-
// console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
|
|
1148
959
|
if (typeof attributeValue === 'undefined')
|
|
1149
960
|
return;
|
|
1150
961
|
if (clusterName === 'onOff' && attributeName === 'onOff')
|
|
@@ -1222,13 +1033,8 @@ export class Frontend {
|
|
|
1222
1033
|
if (clusterName === 'userLabel' && attributeName === 'labelList')
|
|
1223
1034
|
attributes += `${getUserLabel(device)} `;
|
|
1224
1035
|
});
|
|
1225
|
-
// console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
|
|
1226
1036
|
return attributes.trimStart().trimEnd();
|
|
1227
1037
|
}
|
|
1228
|
-
/**
|
|
1229
|
-
* Retrieves the base registered plugins sanitized for res.json().
|
|
1230
|
-
* @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
|
|
1231
|
-
*/
|
|
1232
1038
|
getBaseRegisteredPlugins() {
|
|
1233
1039
|
const baseRegisteredPlugins = [];
|
|
1234
1040
|
for (const plugin of this.matterbridge.plugins) {
|
|
@@ -1261,13 +1067,6 @@ export class Frontend {
|
|
|
1261
1067
|
}
|
|
1262
1068
|
return baseRegisteredPlugins;
|
|
1263
1069
|
}
|
|
1264
|
-
/**
|
|
1265
|
-
* Handles incoming websocket messages for the Matterbridge frontend.
|
|
1266
|
-
*
|
|
1267
|
-
* @param {WebSocket} client - The websocket client that sent the message.
|
|
1268
|
-
* @param {WebSocket.RawData} message - The raw data of the message received from the client.
|
|
1269
|
-
* @returns {Promise<void>} A promise that resolves when the message has been handled.
|
|
1270
|
-
*/
|
|
1271
1070
|
async wsMessageHandler(client, message) {
|
|
1272
1071
|
let data;
|
|
1273
1072
|
try {
|
|
@@ -1413,10 +1212,8 @@ export class Frontend {
|
|
|
1413
1212
|
else if (data.method === '/api/devices') {
|
|
1414
1213
|
const devices = [];
|
|
1415
1214
|
this.matterbridge.devices.forEach(async (device) => {
|
|
1416
|
-
// Filter by pluginName if provided
|
|
1417
1215
|
if (data.params.pluginName && data.params.pluginName !== device.plugin)
|
|
1418
1216
|
return;
|
|
1419
|
-
// Check if the device has the required properties
|
|
1420
1217
|
if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
|
|
1421
1218
|
return;
|
|
1422
1219
|
const cluster = this.getClusterTextFromDevice(device);
|
|
@@ -1500,7 +1297,6 @@ export class Frontend {
|
|
|
1500
1297
|
});
|
|
1501
1298
|
endpointServer.getChildEndpoints().forEach((childEndpoint) => {
|
|
1502
1299
|
deviceTypes = [];
|
|
1503
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1504
1300
|
const name = childEndpoint.endpoint?.id;
|
|
1505
1301
|
const clusterServers = childEndpoint.getAllClusterServers();
|
|
1506
1302
|
clusterServers.forEach((clusterServer) => {
|
|
@@ -1554,7 +1350,6 @@ export class Frontend {
|
|
|
1554
1350
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select' }));
|
|
1555
1351
|
return;
|
|
1556
1352
|
}
|
|
1557
|
-
// const selectDeviceValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectDevice.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
|
|
1558
1353
|
const selectDeviceValues = plugin.platform?.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1559
1354
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectDeviceValues }));
|
|
1560
1355
|
return;
|
|
@@ -1569,38 +1364,62 @@ export class Frontend {
|
|
|
1569
1364
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/entities' }));
|
|
1570
1365
|
return;
|
|
1571
1366
|
}
|
|
1572
|
-
// const selectEntityValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectEntity.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
|
|
1573
1367
|
const selectEntityValues = plugin.platform?.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
|
|
1574
1368
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectEntityValues }));
|
|
1575
1369
|
return;
|
|
1576
1370
|
}
|
|
1371
|
+
else if (data.method === '/api/action') {
|
|
1372
|
+
if (!isValidString(data.params.plugin, 5) || !isValidString(data.params.action, 1)) {
|
|
1373
|
+
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter command in /api/action' }));
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1377
|
+
if (!plugin) {
|
|
1378
|
+
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/action' }));
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
plugin.platform?.onAction(data.params.action, data.params.value).catch((error) => {
|
|
1382
|
+
this.log.error(`Error in plugin ${plugin.name} action ${data.params.action}: ${error}`);
|
|
1383
|
+
});
|
|
1384
|
+
this.log.notice(`Action ${CYAN}${data.params.action}${nt}${data.params.value ? ' with ' + CYAN + data.params.value + nt : ''} for plugin ${CYAN}${plugin.name}${nt}`);
|
|
1385
|
+
}
|
|
1577
1386
|
else if (data.method === '/api/command') {
|
|
1578
1387
|
if (!isValidString(data.params.command, 5)) {
|
|
1579
1388
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter command in /api/command' }));
|
|
1580
1389
|
return;
|
|
1581
1390
|
}
|
|
1582
|
-
if (data.params.command === 'selectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1)) {
|
|
1391
|
+
if (data.params.command === 'selectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1) && isValidString(data.params.name, 1)) {
|
|
1583
1392
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1584
1393
|
if (!plugin) {
|
|
1585
1394
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/command' }));
|
|
1586
1395
|
return;
|
|
1587
1396
|
}
|
|
1588
1397
|
const config = plugin.configJson;
|
|
1589
|
-
|
|
1398
|
+
const select = plugin.schemaJson?.properties?.blackList?.selectFrom;
|
|
1399
|
+
this.log.debug(`SelectDevice(selectMode ${select}) data ${debugStringify(data)}`);
|
|
1400
|
+
if (select === 'serial')
|
|
1401
|
+
this.log.info(`Selected device serial ${data.params.serial}`);
|
|
1402
|
+
if (select === 'name')
|
|
1403
|
+
this.log.info(`Selected device name ${data.params.name}`);
|
|
1404
|
+
if (config && select && (select === 'serial' || select === 'name')) {
|
|
1590
1405
|
if (config.postfix) {
|
|
1591
1406
|
data.params.serial = data.params.serial.replace('-' + config.postfix, '');
|
|
1592
1407
|
}
|
|
1593
|
-
// Add the serial to the whiteList if the whiteList exists and the serial is not already in it
|
|
1594
1408
|
if (isValidArray(config.whiteList, 1)) {
|
|
1595
|
-
if (!config.whiteList.includes(data.params.serial)) {
|
|
1409
|
+
if (select === 'serial' && !config.whiteList.includes(data.params.serial)) {
|
|
1596
1410
|
config.whiteList.push(data.params.serial);
|
|
1597
1411
|
}
|
|
1412
|
+
else if (select === 'name' && !config.whiteList.includes(data.params.name)) {
|
|
1413
|
+
config.whiteList.push(data.params.name);
|
|
1414
|
+
}
|
|
1598
1415
|
}
|
|
1599
|
-
// Remove the serial from the blackList if the blackList exists and the serial is in it
|
|
1600
1416
|
if (isValidArray(config.blackList, 1)) {
|
|
1601
|
-
if (config.blackList.includes(data.params.serial)) {
|
|
1417
|
+
if (select === 'serial' && config.blackList.includes(data.params.serial)) {
|
|
1602
1418
|
config.blackList = config.blackList.filter((serial) => serial !== data.params.serial);
|
|
1603
1419
|
}
|
|
1420
|
+
else if (select === 'name' && config.blackList.includes(data.params.name)) {
|
|
1421
|
+
config.blackList = config.blackList.filter((name) => name !== data.params.name);
|
|
1422
|
+
}
|
|
1604
1423
|
}
|
|
1605
1424
|
if (plugin.platform)
|
|
1606
1425
|
plugin.platform.config = config;
|
|
@@ -1608,28 +1427,38 @@ export class Frontend {
|
|
|
1608
1427
|
this.wssSendRestartRequired(false);
|
|
1609
1428
|
}
|
|
1610
1429
|
}
|
|
1611
|
-
else if (data.params.command === 'unselectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1)) {
|
|
1430
|
+
else if (data.params.command === 'unselectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1) && isValidString(data.params.name, 1)) {
|
|
1612
1431
|
const plugin = this.matterbridge.plugins.get(data.params.plugin);
|
|
1613
1432
|
if (!plugin) {
|
|
1614
1433
|
client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/command' }));
|
|
1615
1434
|
return;
|
|
1616
1435
|
}
|
|
1617
1436
|
const config = plugin.configJson;
|
|
1618
|
-
|
|
1437
|
+
const select = plugin.schemaJson?.properties?.blackList?.selectFrom;
|
|
1438
|
+
this.log.debug(`UnselectDevice(selectMode ${select}) data ${debugStringify(data)}`);
|
|
1439
|
+
if (select === 'serial')
|
|
1440
|
+
this.log.info(`Unselected device serial ${data.params.serial}`);
|
|
1441
|
+
if (select === 'name')
|
|
1442
|
+
this.log.info(`Unselected device name ${data.params.name}`);
|
|
1443
|
+
if (config && select && (select === 'serial' || select === 'name')) {
|
|
1619
1444
|
if (config.postfix) {
|
|
1620
1445
|
data.params.serial = data.params.serial.replace('-' + config.postfix, '');
|
|
1621
1446
|
}
|
|
1622
|
-
// Remove the serial from the whiteList if the whiteList exists and the serial is in it
|
|
1623
1447
|
if (isValidArray(config.whiteList, 1)) {
|
|
1624
|
-
if (config.whiteList.includes(data.params.serial)) {
|
|
1448
|
+
if (select === 'serial' && config.whiteList.includes(data.params.serial)) {
|
|
1625
1449
|
config.whiteList = config.whiteList.filter((serial) => serial !== data.params.serial);
|
|
1626
1450
|
}
|
|
1451
|
+
else if (select === 'name' && config.whiteList.includes(data.params.name)) {
|
|
1452
|
+
config.whiteList = config.whiteList.filter((name) => name !== data.params.name);
|
|
1453
|
+
}
|
|
1627
1454
|
}
|
|
1628
|
-
// Add the serial to the blackList
|
|
1629
1455
|
if (isValidArray(config.blackList)) {
|
|
1630
|
-
if (!config.blackList.includes(data.params.serial)) {
|
|
1456
|
+
if (select === 'serial' && !config.blackList.includes(data.params.serial)) {
|
|
1631
1457
|
config.blackList.push(data.params.serial);
|
|
1632
1458
|
}
|
|
1459
|
+
else if (select === 'name' && !config.blackList.includes(data.params.name)) {
|
|
1460
|
+
config.blackList.push(data.params.name);
|
|
1461
|
+
}
|
|
1633
1462
|
}
|
|
1634
1463
|
if (plugin.platform)
|
|
1635
1464
|
plugin.platform.config = config;
|
|
@@ -1649,194 +1478,102 @@ export class Frontend {
|
|
|
1649
1478
|
return;
|
|
1650
1479
|
}
|
|
1651
1480
|
}
|
|
1652
|
-
/**
|
|
1653
|
-
* Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
|
|
1654
|
-
*
|
|
1655
|
-
* @param {string} level - The logger level of the message: debug info notice warn error fatal...
|
|
1656
|
-
* @param {string} time - The time string of the message
|
|
1657
|
-
* @param {string} name - The logger name of the message
|
|
1658
|
-
* @param {string} message - The content of the message.
|
|
1659
|
-
*/
|
|
1660
1481
|
wssSendMessage(level, time, name, message) {
|
|
1661
1482
|
if (!level || !time || !name || !message)
|
|
1662
1483
|
return;
|
|
1663
|
-
// Remove ANSI escape codes from the message
|
|
1664
|
-
// eslint-disable-next-line no-control-regex
|
|
1665
1484
|
message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
|
|
1666
|
-
// Remove leading asterisks from the message
|
|
1667
1485
|
message = message.replace(/^\*+/, '');
|
|
1668
|
-
// Replace all occurrences of \t and \n
|
|
1669
1486
|
message = message.replace(/[\t\n]/g, '');
|
|
1670
|
-
// Remove non-printable characters
|
|
1671
|
-
// eslint-disable-next-line no-control-regex
|
|
1672
1487
|
message = message.replace(/[\x00-\x1F\x7F]/g, '');
|
|
1673
|
-
// Replace all occurrences of \" with "
|
|
1674
1488
|
message = message.replace(/\\"/g, '"');
|
|
1675
|
-
// Define the maximum allowed length for continuous characters without a space
|
|
1676
1489
|
const maxContinuousLength = 100;
|
|
1677
1490
|
const keepStartLength = 20;
|
|
1678
1491
|
const keepEndLength = 20;
|
|
1679
|
-
// Split the message into words
|
|
1680
1492
|
message = message
|
|
1681
1493
|
.split(' ')
|
|
1682
1494
|
.map((word) => {
|
|
1683
|
-
// If the word length exceeds the max continuous length, insert spaces and truncate
|
|
1684
1495
|
if (word.length > maxContinuousLength) {
|
|
1685
1496
|
return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
|
|
1686
1497
|
}
|
|
1687
1498
|
return word;
|
|
1688
1499
|
})
|
|
1689
1500
|
.join(' ');
|
|
1690
|
-
// Send the message to all connected clients
|
|
1691
1501
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1692
1502
|
if (client.readyState === WebSocket.OPEN) {
|
|
1693
1503
|
client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
|
|
1694
1504
|
}
|
|
1695
1505
|
});
|
|
1696
1506
|
}
|
|
1697
|
-
/**
|
|
1698
|
-
* Sends a need to refresh WebSocket message to all connected clients.
|
|
1699
|
-
*
|
|
1700
|
-
* @param {string} changed - The changed value. If null, the whole page will be refreshed.
|
|
1701
|
-
* possible values:
|
|
1702
|
-
* - 'matterbridgeLatestVersion'
|
|
1703
|
-
* - 'matterbridgeAdvertise'
|
|
1704
|
-
* - 'online'
|
|
1705
|
-
* - 'offline'
|
|
1706
|
-
* - 'reachability'
|
|
1707
|
-
* - 'settings'
|
|
1708
|
-
* - 'plugins'
|
|
1709
|
-
* - 'devices'
|
|
1710
|
-
* - 'fabrics'
|
|
1711
|
-
* - 'sessions'
|
|
1712
|
-
*/
|
|
1713
1507
|
wssSendRefreshRequired(changed = null) {
|
|
1714
1508
|
this.log.debug('Sending a refresh required message to all connected clients');
|
|
1715
|
-
// Send the message to all connected clients
|
|
1716
1509
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1717
1510
|
if (client.readyState === WebSocket.OPEN) {
|
|
1718
1511
|
client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: { changed: changed } }));
|
|
1719
1512
|
}
|
|
1720
1513
|
});
|
|
1721
1514
|
}
|
|
1722
|
-
/**
|
|
1723
|
-
* Sends a need to restart WebSocket message to all connected clients.
|
|
1724
|
-
*
|
|
1725
|
-
*/
|
|
1726
1515
|
wssSendRestartRequired(snackbar = true) {
|
|
1727
1516
|
this.log.debug('Sending a restart required message to all connected clients');
|
|
1728
1517
|
this.matterbridge.matterbridgeInformation.restartRequired = true;
|
|
1729
1518
|
if (snackbar === true)
|
|
1730
1519
|
this.wssSendSnackbarMessage(`Restart required`, 0);
|
|
1731
|
-
// Send the message to all connected clients
|
|
1732
1520
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1733
1521
|
if (client.readyState === WebSocket.OPEN) {
|
|
1734
1522
|
client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
|
|
1735
1523
|
}
|
|
1736
1524
|
});
|
|
1737
1525
|
}
|
|
1738
|
-
/**
|
|
1739
|
-
* Sends a need to update WebSocket message to all connected clients.
|
|
1740
|
-
*
|
|
1741
|
-
*/
|
|
1742
1526
|
wssSendUpdateRequired() {
|
|
1743
1527
|
this.log.debug('Sending an update required message to all connected clients');
|
|
1744
1528
|
this.matterbridge.matterbridgeInformation.updateRequired = true;
|
|
1745
|
-
// Send the message to all connected clients
|
|
1746
1529
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1747
1530
|
if (client.readyState === WebSocket.OPEN) {
|
|
1748
1531
|
client.send(JSON.stringify({ id: WS_ID_UPDATE_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', params: {} }));
|
|
1749
1532
|
}
|
|
1750
1533
|
});
|
|
1751
1534
|
}
|
|
1752
|
-
/**
|
|
1753
|
-
* Sends a memory update message to all connected clients.
|
|
1754
|
-
*
|
|
1755
|
-
*/
|
|
1756
1535
|
wssSendCpuUpdate(cpuUsage) {
|
|
1757
1536
|
this.log.debug('Sending a cpu update message to all connected clients');
|
|
1758
|
-
// Send the message to all connected clients
|
|
1759
1537
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1760
1538
|
if (client.readyState === WebSocket.OPEN) {
|
|
1761
1539
|
client.send(JSON.stringify({ id: WS_ID_CPU_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } }));
|
|
1762
1540
|
}
|
|
1763
1541
|
});
|
|
1764
1542
|
}
|
|
1765
|
-
/**
|
|
1766
|
-
* Sends a cpu update message to all connected clients.
|
|
1767
|
-
*
|
|
1768
|
-
*/
|
|
1769
1543
|
wssSendMemoryUpdate(totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers) {
|
|
1770
1544
|
this.log.debug('Sending a memory update message to all connected clients');
|
|
1771
|
-
// Send the message to all connected clients
|
|
1772
1545
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1773
1546
|
if (client.readyState === WebSocket.OPEN) {
|
|
1774
1547
|
client.send(JSON.stringify({ id: WS_ID_MEMORY_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } }));
|
|
1775
1548
|
}
|
|
1776
1549
|
});
|
|
1777
1550
|
}
|
|
1778
|
-
/**
|
|
1779
|
-
* Sends a memory update message to all connected clients.
|
|
1780
|
-
*
|
|
1781
|
-
*/
|
|
1782
1551
|
wssSendUptimeUpdate(systemUptime, processUptime) {
|
|
1783
1552
|
this.log.debug('Sending a uptime update message to all connected clients');
|
|
1784
|
-
// Send the message to all connected clients
|
|
1785
1553
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1786
1554
|
if (client.readyState === WebSocket.OPEN) {
|
|
1787
1555
|
client.send(JSON.stringify({ id: WS_ID_UPTIME_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } }));
|
|
1788
1556
|
}
|
|
1789
1557
|
});
|
|
1790
1558
|
}
|
|
1791
|
-
/**
|
|
1792
|
-
* Sends a cpu update message to all connected clients.
|
|
1793
|
-
* @param {string} message - The message to send.
|
|
1794
|
-
* @param {number} timeout - The timeout in seconds for the snackbar message.
|
|
1795
|
-
* @param {'info' | 'warning' | 'error' | 'success'} severity - The severity of the snackbar message (default info).
|
|
1796
|
-
*
|
|
1797
|
-
*/
|
|
1798
1559
|
wssSendSnackbarMessage(message, timeout = 5, severity = 'info') {
|
|
1799
1560
|
this.log.debug('Sending a snackbar message to all connected clients');
|
|
1800
|
-
// Send the message to all connected clients
|
|
1801
1561
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1802
1562
|
if (client.readyState === WebSocket.OPEN) {
|
|
1803
1563
|
client.send(JSON.stringify({ id: WS_ID_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { message, timeout, severity } }));
|
|
1804
1564
|
}
|
|
1805
1565
|
});
|
|
1806
1566
|
}
|
|
1807
|
-
/**
|
|
1808
|
-
* Sends an attribute update message to all connected WebSocket clients.
|
|
1809
|
-
*
|
|
1810
|
-
* @param {string | undefined} plugin - The name of the plugin.
|
|
1811
|
-
* @param {string | undefined} serialNumber - The serial number of the device.
|
|
1812
|
-
* @param {string | undefined} uniqueId - The unique identifier of the device.
|
|
1813
|
-
* @param {string} cluster - The cluster name where the attribute belongs.
|
|
1814
|
-
* @param {string} attribute - The name of the attribute that changed.
|
|
1815
|
-
* @param {number | string | boolean} value - The new value of the attribute.
|
|
1816
|
-
*
|
|
1817
|
-
* @remarks
|
|
1818
|
-
* This method logs a debug message and sends a JSON-formatted message to all connected WebSocket clients
|
|
1819
|
-
* with the updated attribute information.
|
|
1820
|
-
*/
|
|
1821
1567
|
wssSendAttributeChangedMessage(plugin, serialNumber, uniqueId, cluster, attribute, value) {
|
|
1822
1568
|
this.log.debug('Sending an attribute update message to all connected clients');
|
|
1823
|
-
// Send the message to all connected clients
|
|
1824
1569
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1825
1570
|
if (client.readyState === WebSocket.OPEN) {
|
|
1826
1571
|
client.send(JSON.stringify({ id: WS_ID_STATEUPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', params: { plugin, serialNumber, uniqueId, cluster, attribute, value } }));
|
|
1827
1572
|
}
|
|
1828
1573
|
});
|
|
1829
1574
|
}
|
|
1830
|
-
/**
|
|
1831
|
-
* Sends a message to all connected clients.
|
|
1832
|
-
* @param {number} id - The message id.
|
|
1833
|
-
* @param {string} method - The message method.
|
|
1834
|
-
* @param {Record<string, string | number | boolean>} params - The message parameters.
|
|
1835
|
-
*
|
|
1836
|
-
*/
|
|
1837
1575
|
wssBroadcastMessage(id, method, params) {
|
|
1838
1576
|
this.log.debug(`Sending a broadcast message id ${id} method ${method} params ${debugStringify(params ?? {})} to all connected clients`);
|
|
1839
|
-
// Send the message to all connected clients
|
|
1840
1577
|
this.webSocketServer?.clients.forEach((client) => {
|
|
1841
1578
|
if (client.readyState === WebSocket.OPEN) {
|
|
1842
1579
|
client.send(JSON.stringify({ id, src: 'Matterbridge', dst: 'Frontend', method, params }));
|
|
@@ -1844,4 +1581,3 @@ export class Frontend {
|
|
|
1844
1581
|
});
|
|
1845
1582
|
}
|
|
1846
1583
|
}
|
|
1847
|
-
//# sourceMappingURL=frontend.js.map
|