matterbridge 3.3.7 → 3.3.8-dev-20251115-920acfc
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 +37 -0
- package/README-SERVICE-OPT.md +4 -4
- package/README.md +4 -0
- package/dist/broadcastServer.js +1 -93
- package/dist/broadcastServerTypes.js +0 -24
- package/dist/cli.js +1 -97
- package/dist/cliEmitter.js +0 -37
- package/dist/cliHistory.js +0 -38
- package/dist/clusters/export.js +0 -2
- package/dist/defaultConfigSchema.js +0 -24
- package/dist/deviceManager.js +1 -105
- package/dist/devices/airConditioner.js +1 -58
- package/dist/devices/batteryStorage.js +2 -49
- package/dist/devices/cooktop.js +1 -56
- package/dist/devices/dishwasher.js +1 -58
- package/dist/devices/evse.js +11 -75
- package/dist/devices/export.js +0 -5
- package/dist/devices/extractorHood.js +1 -43
- package/dist/devices/heatPump.js +3 -51
- package/dist/devices/laundryDryer.js +4 -63
- package/dist/devices/laundryWasher.js +5 -71
- package/dist/devices/microwaveOven.js +6 -89
- package/dist/devices/oven.js +1 -86
- package/dist/devices/refrigerator.js +2 -104
- package/dist/devices/roboticVacuumCleaner.js +10 -101
- package/dist/devices/solarPower.js +1 -39
- package/dist/devices/speaker.js +1 -85
- package/dist/devices/temperatureControl.js +3 -24
- package/dist/devices/waterHeater.js +3 -83
- package/dist/dgram/coap.js +13 -126
- package/dist/dgram/dgram.js +2 -114
- package/dist/dgram/mb_coap.js +3 -41
- package/dist/dgram/mb_mdns.js +15 -80
- package/dist/dgram/mdns.js +137 -299
- package/dist/dgram/multicast.js +1 -62
- package/dist/dgram/unicast.js +0 -54
- package/dist/frontend.js +40 -452
- package/dist/frontendTypes.js +0 -45
- package/dist/helpers.js +0 -53
- package/dist/index.js +1 -25
- package/dist/jestutils/export.js +1 -0
- package/dist/{utils → jestutils}/jestHelpers.js +167 -175
- 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 -3
- package/dist/matter/types.js +0 -3
- package/dist/matterbridge.js +50 -838
- package/dist/matterbridgeAccessoryPlatform.js +0 -37
- package/dist/matterbridgeBehaviors.js +5 -68
- package/dist/matterbridgeDeviceTypes.js +27 -653
- package/dist/matterbridgeDynamicPlatform.js +0 -37
- package/dist/matterbridgeEndpoint.js +74 -1429
- package/dist/matterbridgeEndpointHelpers.js +42 -475
- package/dist/matterbridgeEndpointTypes.js +3 -0
- package/dist/matterbridgePlatform.js +18 -341
- package/dist/matterbridgeTypes.js +0 -26
- package/dist/pluginManager.js +5 -340
- package/dist/shelly.js +7 -168
- package/dist/storage/export.js +0 -1
- package/dist/update.js +0 -69
- package/dist/utils/colorUtils.js +2 -97
- package/dist/utils/commandLine.js +0 -60
- package/dist/utils/copyDirectory.js +1 -38
- package/dist/utils/createDirectory.js +0 -33
- package/dist/utils/createZip.js +2 -47
- package/dist/utils/deepCopy.js +0 -39
- package/dist/utils/deepEqual.js +1 -72
- package/dist/utils/error.js +2 -43
- package/dist/utils/export.js +0 -1
- package/dist/utils/format.js +0 -49
- package/dist/utils/hex.js +0 -124
- package/dist/utils/inspector.js +1 -69
- package/dist/utils/isvalid.js +0 -101
- package/dist/utils/network.js +5 -96
- package/dist/utils/spawn.js +0 -71
- package/dist/utils/tracker.js +1 -64
- package/dist/utils/wait.js +8 -60
- package/npm-shrinkwrap.json +8 -8
- package/package.json +5 -2
- package/scripts/fetch-chip.mjs +100 -0
- package/dist/broadcastServer.d.ts +0 -115
- package/dist/broadcastServer.d.ts.map +0 -1
- package/dist/broadcastServer.js.map +0 -1
- package/dist/broadcastServerTypes.d.ts +0 -806
- package/dist/broadcastServerTypes.d.ts.map +0 -1
- package/dist/broadcastServerTypes.js.map +0 -1
- package/dist/cli.d.ts +0 -30
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cliEmitter.d.ts +0 -50
- package/dist/cliEmitter.d.ts.map +0 -1
- package/dist/cliEmitter.js.map +0 -1
- package/dist/cliHistory.d.ts +0 -48
- package/dist/cliHistory.d.ts.map +0 -1
- package/dist/cliHistory.js.map +0 -1
- package/dist/clusters/export.d.ts +0 -2
- package/dist/clusters/export.d.ts.map +0 -1
- package/dist/clusters/export.js.map +0 -1
- package/dist/defaultConfigSchema.d.ts +0 -28
- package/dist/defaultConfigSchema.d.ts.map +0 -1
- package/dist/defaultConfigSchema.js.map +0 -1
- package/dist/deviceManager.d.ts +0 -128
- package/dist/deviceManager.d.ts.map +0 -1
- package/dist/deviceManager.js.map +0 -1
- package/dist/devices/airConditioner.d.ts +0 -98
- package/dist/devices/airConditioner.d.ts.map +0 -1
- package/dist/devices/airConditioner.js.map +0 -1
- package/dist/devices/batteryStorage.d.ts +0 -48
- package/dist/devices/batteryStorage.d.ts.map +0 -1
- package/dist/devices/batteryStorage.js.map +0 -1
- package/dist/devices/cooktop.d.ts +0 -60
- package/dist/devices/cooktop.d.ts.map +0 -1
- package/dist/devices/cooktop.js.map +0 -1
- package/dist/devices/dishwasher.d.ts +0 -71
- package/dist/devices/dishwasher.d.ts.map +0 -1
- package/dist/devices/dishwasher.js.map +0 -1
- package/dist/devices/evse.d.ts +0 -76
- package/dist/devices/evse.d.ts.map +0 -1
- package/dist/devices/evse.js.map +0 -1
- package/dist/devices/export.d.ts +0 -17
- package/dist/devices/export.d.ts.map +0 -1
- package/dist/devices/export.js.map +0 -1
- package/dist/devices/extractorHood.d.ts +0 -46
- package/dist/devices/extractorHood.d.ts.map +0 -1
- package/dist/devices/extractorHood.js.map +0 -1
- package/dist/devices/heatPump.d.ts +0 -47
- package/dist/devices/heatPump.d.ts.map +0 -1
- package/dist/devices/heatPump.js.map +0 -1
- package/dist/devices/laundryDryer.d.ts +0 -67
- package/dist/devices/laundryDryer.d.ts.map +0 -1
- package/dist/devices/laundryDryer.js.map +0 -1
- package/dist/devices/laundryWasher.d.ts +0 -81
- package/dist/devices/laundryWasher.d.ts.map +0 -1
- package/dist/devices/laundryWasher.js.map +0 -1
- package/dist/devices/microwaveOven.d.ts +0 -168
- package/dist/devices/microwaveOven.d.ts.map +0 -1
- package/dist/devices/microwaveOven.js.map +0 -1
- package/dist/devices/oven.d.ts +0 -105
- package/dist/devices/oven.d.ts.map +0 -1
- package/dist/devices/oven.js.map +0 -1
- package/dist/devices/refrigerator.d.ts +0 -118
- package/dist/devices/refrigerator.d.ts.map +0 -1
- package/dist/devices/refrigerator.js.map +0 -1
- package/dist/devices/roboticVacuumCleaner.d.ts +0 -112
- package/dist/devices/roboticVacuumCleaner.d.ts.map +0 -1
- package/dist/devices/roboticVacuumCleaner.js.map +0 -1
- package/dist/devices/solarPower.d.ts +0 -40
- package/dist/devices/solarPower.d.ts.map +0 -1
- package/dist/devices/solarPower.js.map +0 -1
- package/dist/devices/speaker.d.ts +0 -87
- package/dist/devices/speaker.d.ts.map +0 -1
- package/dist/devices/speaker.js.map +0 -1
- package/dist/devices/temperatureControl.d.ts +0 -166
- package/dist/devices/temperatureControl.d.ts.map +0 -1
- package/dist/devices/temperatureControl.js.map +0 -1
- package/dist/devices/waterHeater.d.ts +0 -111
- package/dist/devices/waterHeater.d.ts.map +0 -1
- package/dist/devices/waterHeater.js.map +0 -1
- package/dist/dgram/coap.d.ts +0 -205
- package/dist/dgram/coap.d.ts.map +0 -1
- package/dist/dgram/coap.js.map +0 -1
- package/dist/dgram/dgram.d.ts +0 -141
- package/dist/dgram/dgram.d.ts.map +0 -1
- package/dist/dgram/dgram.js.map +0 -1
- package/dist/dgram/mb_coap.d.ts +0 -24
- package/dist/dgram/mb_coap.d.ts.map +0 -1
- package/dist/dgram/mb_coap.js.map +0 -1
- package/dist/dgram/mb_mdns.d.ts +0 -24
- package/dist/dgram/mb_mdns.d.ts.map +0 -1
- package/dist/dgram/mb_mdns.js.map +0 -1
- package/dist/dgram/mdns.d.ts +0 -290
- package/dist/dgram/mdns.d.ts.map +0 -1
- package/dist/dgram/mdns.js.map +0 -1
- package/dist/dgram/multicast.d.ts +0 -67
- package/dist/dgram/multicast.d.ts.map +0 -1
- package/dist/dgram/multicast.js.map +0 -1
- package/dist/dgram/unicast.d.ts +0 -56
- package/dist/dgram/unicast.d.ts.map +0 -1
- package/dist/dgram/unicast.js.map +0 -1
- package/dist/frontend.d.ts +0 -238
- package/dist/frontend.d.ts.map +0 -1
- package/dist/frontend.js.map +0 -1
- package/dist/frontendTypes.d.ts +0 -529
- package/dist/frontendTypes.d.ts.map +0 -1
- package/dist/frontendTypes.js.map +0 -1
- package/dist/helpers.d.ts +0 -48
- package/dist/helpers.d.ts.map +0 -1
- package/dist/helpers.js.map +0 -1
- package/dist/index.d.ts +0 -33
- 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 -478
- package/dist/matterbridge.d.ts.map +0 -1
- package/dist/matterbridge.js.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +0 -42
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
- package/dist/matterbridgeBehaviors.d.ts +0 -2404
- package/dist/matterbridgeBehaviors.d.ts.map +0 -1
- package/dist/matterbridgeBehaviors.js.map +0 -1
- package/dist/matterbridgeDeviceTypes.d.ts +0 -770
- package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
- package/dist/matterbridgeDeviceTypes.js.map +0 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +0 -42
- package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
- package/dist/matterbridgeDynamicPlatform.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts +0 -1556
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgeEndpointHelpers.d.ts +0 -758
- package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
- package/dist/matterbridgeEndpointHelpers.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts +0 -402
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts +0 -239
- package/dist/matterbridgeTypes.d.ts.map +0 -1
- package/dist/matterbridgeTypes.js.map +0 -1
- package/dist/pluginManager.d.ts +0 -371
- package/dist/pluginManager.d.ts.map +0 -1
- package/dist/pluginManager.js.map +0 -1
- package/dist/shelly.d.ts +0 -174
- 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 -75
- package/dist/update.d.ts.map +0 -1
- package/dist/update.js.map +0 -1
- package/dist/utils/colorUtils.d.ts +0 -101
- package/dist/utils/colorUtils.d.ts.map +0 -1
- package/dist/utils/colorUtils.js.map +0 -1
- package/dist/utils/commandLine.d.ts +0 -66
- package/dist/utils/commandLine.d.ts.map +0 -1
- package/dist/utils/commandLine.js.map +0 -1
- package/dist/utils/copyDirectory.d.ts +0 -33
- package/dist/utils/copyDirectory.d.ts.map +0 -1
- package/dist/utils/copyDirectory.js.map +0 -1
- package/dist/utils/createDirectory.d.ts +0 -34
- package/dist/utils/createDirectory.d.ts.map +0 -1
- package/dist/utils/createDirectory.js.map +0 -1
- package/dist/utils/createZip.d.ts +0 -39
- package/dist/utils/createZip.d.ts.map +0 -1
- package/dist/utils/createZip.js.map +0 -1
- package/dist/utils/deepCopy.d.ts +0 -32
- package/dist/utils/deepCopy.d.ts.map +0 -1
- package/dist/utils/deepCopy.js.map +0 -1
- package/dist/utils/deepEqual.d.ts +0 -54
- package/dist/utils/deepEqual.d.ts.map +0 -1
- package/dist/utils/deepEqual.js.map +0 -1
- package/dist/utils/error.d.ts +0 -44
- package/dist/utils/error.d.ts.map +0 -1
- package/dist/utils/error.js.map +0 -1
- package/dist/utils/export.d.ts +0 -13
- package/dist/utils/export.d.ts.map +0 -1
- package/dist/utils/export.js.map +0 -1
- package/dist/utils/format.d.ts +0 -53
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/hex.d.ts +0 -89
- package/dist/utils/hex.d.ts.map +0 -1
- package/dist/utils/hex.js.map +0 -1
- package/dist/utils/inspector.d.ts +0 -87
- package/dist/utils/inspector.d.ts.map +0 -1
- package/dist/utils/inspector.js.map +0 -1
- package/dist/utils/isvalid.d.ts +0 -103
- package/dist/utils/isvalid.d.ts.map +0 -1
- package/dist/utils/isvalid.js.map +0 -1
- package/dist/utils/jestHelpers.d.ts +0 -139
- package/dist/utils/jestHelpers.d.ts.map +0 -1
- package/dist/utils/jestHelpers.js.map +0 -1
- package/dist/utils/network.d.ts +0 -101
- package/dist/utils/network.d.ts.map +0 -1
- package/dist/utils/network.js.map +0 -1
- package/dist/utils/spawn.d.ts +0 -35
- package/dist/utils/spawn.d.ts.map +0 -1
- package/dist/utils/spawn.js.map +0 -1
- package/dist/utils/tracker.d.ts +0 -108
- package/dist/utils/tracker.d.ts.map +0 -1
- package/dist/utils/tracker.js.map +0 -1
- package/dist/utils/wait.d.ts +0 -54
- package/dist/utils/wait.d.ts.map +0 -1
- package/dist/utils/wait.js.map +0 -1
package/dist/devices/speaker.js
CHANGED
|
@@ -1,104 +1,26 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Speaker device class controlling mute (On/Off) and volume level (Level Control).
|
|
3
|
-
* @file src/devices/speaker.ts
|
|
4
|
-
* @author Luca Liguori
|
|
5
|
-
* @created 2025-09-04
|
|
6
|
-
* @version 1.0.0
|
|
7
|
-
* @license Apache-2.0
|
|
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 clusters
|
|
24
1
|
import { OnOff } from '@matter/types/clusters/on-off';
|
|
25
2
|
import { LevelControl } from '@matter/types/clusters/level-control';
|
|
26
|
-
// matterbridge
|
|
27
3
|
import { speakerDevice } from '../matterbridgeDeviceTypes.js';
|
|
28
4
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
29
|
-
/**
|
|
30
|
-
* Represents a Speaker endpoint (Device Type 0x0022) exposing mute (OnOff) and volume (LevelControl).
|
|
31
|
-
*
|
|
32
|
-
* Mapping:
|
|
33
|
-
* - OnOff TRUE => audio unmuted
|
|
34
|
-
* - OnOff FALSE => audio muted
|
|
35
|
-
* - LevelControl.currentLevel (1..254) => volume (linear map to 0..100%)
|
|
36
|
-
*
|
|
37
|
-
* Edge cases:
|
|
38
|
-
* - Volume < 1 coerced to 1.
|
|
39
|
-
* - Volume > 254 coerced to 254.
|
|
40
|
-
* - Non‑finite volume falls back to 128 (≈ mid level).
|
|
41
|
-
*/
|
|
42
5
|
export class Speaker extends MatterbridgeEndpoint {
|
|
43
|
-
/**
|
|
44
|
-
* Create Speaker endpoint.
|
|
45
|
-
*
|
|
46
|
-
* @param {string} name Human readable device name.
|
|
47
|
-
* @param {string} serial Unique serial (used to derive storage key).
|
|
48
|
-
* @param {boolean} muted Initial muted state (true => unmuted, default true if omitted).
|
|
49
|
-
* @param {number} volume Initial volume (1..254, coerced; default 128 ≈ 50% if omitted).
|
|
50
|
-
* @returns {Speaker} New speaker instance.
|
|
51
|
-
*
|
|
52
|
-
* @remarks Supported by:
|
|
53
|
-
* - SmartThings (OnOff mute, LevelControl volume)
|
|
54
|
-
* - Google Home (OnOff mute, LevelControl volume)
|
|
55
|
-
*/
|
|
56
6
|
constructor(name, serial, muted = false, volume = 128) {
|
|
57
|
-
// sanitize volume
|
|
58
7
|
if (!Number.isFinite(volume))
|
|
59
8
|
volume = 128;
|
|
60
9
|
if (volume < 1)
|
|
61
10
|
volume = 1;
|
|
62
11
|
if (volume > 254)
|
|
63
12
|
volume = 254;
|
|
64
|
-
super([speakerDevice], {
|
|
13
|
+
super([speakerDevice], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
|
|
65
14
|
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Speaker');
|
|
66
|
-
// On/Off used for mute state (TRUE => unmuted) - using no features
|
|
67
15
|
this.createOnOffClusterServer(!muted);
|
|
68
|
-
// LevelControl for volume - using no features
|
|
69
16
|
this.createLevelControlClusterServer(volume);
|
|
70
17
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Set mute state (true => muted / audio off).
|
|
73
|
-
*
|
|
74
|
-
* Edge cases:
|
|
75
|
-
* - Strict boolean; caller must pass boolean (TS enforces).
|
|
76
|
-
*
|
|
77
|
-
* @param {boolean} muted Desired mute state (true => muted, false => unmuted).
|
|
78
|
-
* @returns {Promise<void>} Resolves when attribute is updated.
|
|
79
|
-
*/
|
|
80
18
|
async setMuted(muted) {
|
|
81
19
|
await this.setAttribute(OnOff.Cluster.id, 'onOff', !muted);
|
|
82
20
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Get mute state.
|
|
85
|
-
*
|
|
86
|
-
* @returns {boolean} TRUE when muted, FALSE when unmuted.
|
|
87
|
-
*/
|
|
88
21
|
isMuted() {
|
|
89
22
|
return !this.getAttribute(OnOff.Cluster.id, 'onOff');
|
|
90
23
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Set volume level (1..254).
|
|
93
|
-
*
|
|
94
|
-
* Edge cases:
|
|
95
|
-
* - Non‑finite input ignored.
|
|
96
|
-
* - <1 coerced to 1.
|
|
97
|
-
* - >254 coerced to 254.
|
|
98
|
-
*
|
|
99
|
-
* @param {number} level Raw level (1..254 recommended, coerced if outside range).
|
|
100
|
-
* @returns {Promise<void>} Resolves when attribute is updated.
|
|
101
|
-
*/
|
|
102
24
|
async setVolume(level) {
|
|
103
25
|
if (!Number.isFinite(level))
|
|
104
26
|
return;
|
|
@@ -108,13 +30,7 @@ export class Speaker extends MatterbridgeEndpoint {
|
|
|
108
30
|
level = 254;
|
|
109
31
|
await this.setAttribute(LevelControl.Cluster.id, 'currentLevel', level);
|
|
110
32
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Get current volume.
|
|
113
|
-
*
|
|
114
|
-
* @returns {number} Current level (1..254).
|
|
115
|
-
*/
|
|
116
33
|
getVolume() {
|
|
117
34
|
return this.getAttribute(LevelControl.Cluster.id, 'currentLevel');
|
|
118
35
|
}
|
|
119
36
|
}
|
|
120
|
-
//# sourceMappingURL=speaker.js.map
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { TemperatureControl } from '@matter/types/clusters/temperature-control';
|
|
2
2
|
import { TemperatureControlServer } from '@matter/node/behaviors/temperature-control';
|
|
3
3
|
import { MatterbridgeServer } from '../matterbridgeBehaviors.js';
|
|
4
|
-
/**
|
|
5
|
-
* Creates a TemperatureControl Cluster Server with feature TemperatureLevel.
|
|
6
|
-
*
|
|
7
|
-
* @param {MatterbridgeEndpoint} endpoint - The Matterbridge endpoint instance.
|
|
8
|
-
* @param {number} selectedTemperatureLevel - The selected temperature level as an index of the supportedTemperatureLevels array. Defaults to 1 (which corresponds to 'Warm').
|
|
9
|
-
* @param {string[]} supportedTemperatureLevels - The supported temperature levels. Defaults to ['Cold', 'Warm', 'Hot', '30°', '40°', '60°', '80°'].
|
|
10
|
-
*
|
|
11
|
-
* @returns {this} The current MatterbridgeEndpoint instance for chaining.
|
|
12
|
-
*/
|
|
13
4
|
export function createLevelTemperatureControlClusterServer(endpoint, selectedTemperatureLevel = 1, supportedTemperatureLevels = ['Cold', 'Warm', 'Hot', '30°', '40°', '60°', '80°']) {
|
|
14
5
|
endpoint.behaviors.require(MatterbridgeLevelTemperatureControlServer.with(TemperatureControl.Feature.TemperatureLevel), {
|
|
15
6
|
selectedTemperatureLevel,
|
|
@@ -17,23 +8,12 @@ export function createLevelTemperatureControlClusterServer(endpoint, selectedTem
|
|
|
17
8
|
});
|
|
18
9
|
return endpoint;
|
|
19
10
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Creates a TemperatureControl Cluster Server with features TemperatureNumber and TemperatureStep.
|
|
22
|
-
*
|
|
23
|
-
* @param {MatterbridgeEndpoint} endpoint - The Matterbridge endpoint instance.
|
|
24
|
-
* @param {number} temperatureSetpoint - The temperature setpoint * 100. Defaults to 40 * 100 (which corresponds to 40°C).
|
|
25
|
-
* @param {number} minTemperature - The minimum temperature * 100. Defaults to 30 * 100 (which corresponds to 30°C). Fixed attribute.
|
|
26
|
-
* @param {number} maxTemperature - The maximum temperature * 100. Defaults to 60 * 100 (which corresponds to 60°C). Fixed attribute.
|
|
27
|
-
* @param {number} [step] - The step size for temperature changes. Defaults to 10 * 100 (which corresponds to 10°C). Fixed attribute.
|
|
28
|
-
*
|
|
29
|
-
* @returns {this} The current MatterbridgeEndpoint instance for chaining.
|
|
30
|
-
*/
|
|
31
11
|
export function createNumberTemperatureControlClusterServer(endpoint, temperatureSetpoint = 40 * 100, minTemperature = 30 * 100, maxTemperature = 60 * 100, step = 10 * 100) {
|
|
32
12
|
endpoint.behaviors.require(MatterbridgeNumberTemperatureControlServer.with(TemperatureControl.Feature.TemperatureNumber, TemperatureControl.Feature.TemperatureStep), {
|
|
33
13
|
temperatureSetpoint,
|
|
34
|
-
minTemperature,
|
|
35
|
-
maxTemperature,
|
|
36
|
-
step,
|
|
14
|
+
minTemperature,
|
|
15
|
+
maxTemperature,
|
|
16
|
+
step,
|
|
37
17
|
});
|
|
38
18
|
return endpoint;
|
|
39
19
|
}
|
|
@@ -75,4 +55,3 @@ export class MatterbridgeNumberTemperatureControlServer extends TemperatureContr
|
|
|
75
55
|
}
|
|
76
56
|
}
|
|
77
57
|
}
|
|
78
|
-
//# sourceMappingURL=temperatureControl.js.map
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description This file contains the WaterHeater class.
|
|
3
|
-
* @file src/devices/waterHeater.ts
|
|
4
|
-
* @author Luca Liguori
|
|
5
|
-
* @contributor Ludovic BOUÉ
|
|
6
|
-
* @created 2025-05-18
|
|
7
|
-
* @version 1.1.0
|
|
8
|
-
* @license Apache-2.0
|
|
9
|
-
*
|
|
10
|
-
* Copyright 2025, 2026, 2027 Luca Liguori.
|
|
11
|
-
*
|
|
12
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
-
* you may not use this file except in compliance with the License.
|
|
14
|
-
* You may obtain a copy of the License at
|
|
15
|
-
*
|
|
16
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
-
*
|
|
18
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
-
* See the License for the specific language governing permissions and
|
|
22
|
-
* limitations under the License.
|
|
23
|
-
*/
|
|
24
1
|
import { ModeBase } from '@matter/types/clusters/mode-base';
|
|
25
2
|
import { WaterHeaterManagement } from '@matter/types/clusters/water-heater-management';
|
|
26
3
|
import { WaterHeaterMode } from '@matter/types/clusters/water-heater-mode';
|
|
@@ -31,31 +8,8 @@ import { MatterbridgeServer } from '../matterbridgeBehaviors.js';
|
|
|
31
8
|
import { electricalSensor, powerSource, waterHeater } from '../matterbridgeDeviceTypes.js';
|
|
32
9
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
33
10
|
export class WaterHeater extends MatterbridgeEndpoint {
|
|
34
|
-
/**
|
|
35
|
-
* Creates an instance of the WaterHeater class.
|
|
36
|
-
*
|
|
37
|
-
* @param {string} name - The name of the water heater.
|
|
38
|
-
* @param {string} serial - The serial number of the water heater.
|
|
39
|
-
* @param {number} [waterTemperature] - The current water temperature. Defaults to 50.
|
|
40
|
-
* @param {number} [targetWaterTemperature] - The target water temperature. Defaults to 55.
|
|
41
|
-
* @param {number} [minHeatSetpointLimit] - The minimum heat setpoint limit. Defaults to 20.
|
|
42
|
-
* @param {number} [maxHeatSetpointLimit] - The maximum heat setpoint limit. Defaults to 80.
|
|
43
|
-
* @param {{ immersionElement1?: boolean; immersionElement2?: boolean; heatPump?: boolean; boiler?: boolean; other?: boolean }} [heaterTypes] - Indicates the heat sources that the water heater can call on for heating. Defaults to { immersionElement1: true }.
|
|
44
|
-
* @param {boolean} heaterTypes.immersionElement1 - Indicates if the water heater has an immersion element 1. Defaults to true.
|
|
45
|
-
* @param {boolean} heaterTypes.immersionElement2 - Indicates if the water heater has an immersion element 2.
|
|
46
|
-
* @param {boolean} heaterTypes.heatPump - Indicates if the water heater has a heat pump.
|
|
47
|
-
* @param {boolean} heaterTypes.boiler - Indicates if the water heater has a boiler.
|
|
48
|
-
* @param {boolean} heaterTypes.other - Indicates if the water heater has other types of heating sources.
|
|
49
|
-
* @param {number} [tankPercentage] - The current tank percentage of the WaterHeaterManagement cluster. Defaults to 90.
|
|
50
|
-
* @param {number} [voltage] - The voltage value in millivolts. Defaults to null if not provided.
|
|
51
|
-
* @param {number} [current] - The current value in milliamperes. Defaults to null if not provided.
|
|
52
|
-
* @param {number} [power] - The power value in milliwatts. Defaults to null if not provided.
|
|
53
|
-
* @param {number} [energy] - The total consumption value in mW/h. Defaults to null if not provided.
|
|
54
|
-
* @param {number} [absMinPower] - Indicate the minimum electrical power in mw that the ESA can consume when switched on. Defaults to `0` if not provided.
|
|
55
|
-
* @param {number} [absMaxPower] - Indicate the maximum electrical power in mw that the ESA can consume when switched on. Defaults to `0` if not provided.
|
|
56
|
-
*/
|
|
57
11
|
constructor(name, serial, waterTemperature = 50, targetWaterTemperature = 55, minHeatSetpointLimit = 20, maxHeatSetpointLimit = 80, heaterTypes = { immersionElement1: true }, tankPercentage = 90, voltage = null, current = null, power = null, energy = null, absMinPower = 0, absMaxPower = 0) {
|
|
58
|
-
super([waterHeater, powerSource, electricalSensor], {
|
|
12
|
+
super([waterHeater, powerSource, electricalSensor], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
|
|
59
13
|
this.createDefaultIdentifyClusterServer()
|
|
60
14
|
.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Water Heater')
|
|
61
15
|
.createDefaultPowerSourceWiredClusterServer()
|
|
@@ -68,42 +22,15 @@ export class WaterHeater extends MatterbridgeEndpoint {
|
|
|
68
22
|
.createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.WaterHeating, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
|
|
69
23
|
.createDefaultDeviceEnergyManagementModeClusterServer();
|
|
70
24
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Creates a default WaterHeaterManagement Cluster Server.
|
|
73
|
-
*
|
|
74
|
-
* @param {{ immersionElement1?: boolean; immersionElement2?: boolean; heatPump?: boolean; boiler?: boolean; other?: boolean }} [heaterTypes] - Indicates the heat sources that the water heater can call on for heating. Defaults to { immersionElement1: true }.
|
|
75
|
-
* @param {boolean} heaterTypes.immersionElement1 - Indicates if the water heater has an immersion element 1. Defaults to true.
|
|
76
|
-
* @param {boolean} heaterTypes.immersionElement2 - Indicates if the water heater has an immersion element 2.
|
|
77
|
-
* @param {boolean} heaterTypes.heatPump - Indicates if the water heater has a heat pump.
|
|
78
|
-
* @param {boolean} heaterTypes.boiler - Indicates if the water heater has a boiler.
|
|
79
|
-
* @param {boolean} heaterTypes.other - Indicates if the water heater has other types of heating sources.
|
|
80
|
-
* @param {{ immersionElement1?: boolean; immersionElement2?: boolean; heatPump?: boolean; boiler?: boolean; other?: boolean }} [heatDemand] - Indicates if the water heater is heating water. Defaults to all heat sources unset.
|
|
81
|
-
* @param {boolean} heatDemand.immersionElement1 - Indicates if the water heater is heating water with immersion element 1. Defaults to false.
|
|
82
|
-
* @param {boolean} heatDemand.immersionElement2 - Indicates if the water heater is heating water with immersion element 2.
|
|
83
|
-
* @param {boolean} heatDemand.heatPump - Indicates if the water heater is heating water with a heat pump.
|
|
84
|
-
* @param {boolean} heatDemand.boiler - Indicates if the water heater is heating water with a boiler.
|
|
85
|
-
* @param {boolean} heatDemand.other - Indicates if the water heater is heating water with other types of heating sources.
|
|
86
|
-
* @param {number} [tankPercentage] - The current tank percentage of the WaterHeaterManagement cluster. Defaults to 100.
|
|
87
|
-
* @param {WaterHeaterManagement.BoostState} [boostState] - The current boost state of the WaterHeaterManagement cluster. Defaults to Inactive.
|
|
88
|
-
* @returns {this} The current MatterbridgeEndpoint instance for chaining.
|
|
89
|
-
*/
|
|
90
25
|
createDefaultWaterHeaterManagementClusterServer(heaterTypes, heatDemand, tankPercentage, boostState) {
|
|
91
26
|
this.behaviors.require(MatterbridgeWaterHeaterManagementServer.with(WaterHeaterManagement.Feature.TankPercent), {
|
|
92
|
-
heaterTypes: heaterTypes ?? { immersionElement1: true },
|
|
27
|
+
heaterTypes: heaterTypes ?? { immersionElement1: true },
|
|
93
28
|
heatDemand: heatDemand ?? {},
|
|
94
29
|
tankPercentage: tankPercentage ?? 100,
|
|
95
30
|
boostState: boostState ?? WaterHeaterManagement.BoostState.Inactive,
|
|
96
31
|
});
|
|
97
32
|
return this;
|
|
98
33
|
}
|
|
99
|
-
/**
|
|
100
|
-
* Creates a default WaterHeaterMode Cluster Server.
|
|
101
|
-
*
|
|
102
|
-
* @param {number} [currentMode] - The current mode of the WaterHeaterMode cluster. Defaults to mode 1 (WaterHeaterMode.ModeTag.Auto).
|
|
103
|
-
* @param {WaterHeaterMode.ModeOption[]} [supportedModes] - The supported modes for the WaterHeaterMode cluster. Defaults all cluster modes.
|
|
104
|
-
*
|
|
105
|
-
* @returns {this} The current MatterbridgeEndpoint instance for chaining.
|
|
106
|
-
*/
|
|
107
34
|
createDefaultWaterHeaterModeClusterServer(currentMode, supportedModes) {
|
|
108
35
|
this.behaviors.require(MatterbridgeWaterHeaterModeServer, {
|
|
109
36
|
supportedModes: supportedModes ?? [
|
|
@@ -120,7 +47,7 @@ export class WaterHeater extends MatterbridgeEndpoint {
|
|
|
120
47
|
{ label: 'Off', mode: 11, modeTags: [{ value: WaterHeaterMode.ModeTag.Off }] },
|
|
121
48
|
{ label: 'Manual', mode: 12, modeTags: [{ value: WaterHeaterMode.ModeTag.Manual }] },
|
|
122
49
|
{ label: 'Timed', mode: 13, modeTags: [{ value: WaterHeaterMode.ModeTag.Timed }] },
|
|
123
|
-
],
|
|
50
|
+
],
|
|
124
51
|
currentMode: currentMode ?? 1,
|
|
125
52
|
});
|
|
126
53
|
return this;
|
|
@@ -133,9 +60,6 @@ export class MatterbridgeWaterHeaterManagementServer extends WaterHeaterManageme
|
|
|
133
60
|
device.commandHandler.executeHandler('boost', { request, cluster: WaterHeaterManagementServer.id, attributes: this.state, endpoint: this.endpoint });
|
|
134
61
|
device.log.debug(`MatterbridgeWaterHeaterManagementServer boost called with: ${JSON.stringify(request)}`);
|
|
135
62
|
this.state.boostState = WaterHeaterManagement.BoostState.Active;
|
|
136
|
-
// The implementation is responsible for setting the device accordingly with the boostInfo of the boost command
|
|
137
|
-
// super.boost({ boostInfo });
|
|
138
|
-
// boost is not implemented in matter.js
|
|
139
63
|
}
|
|
140
64
|
cancelBoost() {
|
|
141
65
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -143,9 +67,6 @@ export class MatterbridgeWaterHeaterManagementServer extends WaterHeaterManageme
|
|
|
143
67
|
device.commandHandler.executeHandler('cancelBoost', { request: {}, cluster: WaterHeaterManagementServer.id, attributes: this.state, endpoint: this.endpoint });
|
|
144
68
|
device.log.debug(`MatterbridgeWaterHeaterManagementServer cancelBoost called`);
|
|
145
69
|
this.state.boostState = WaterHeaterManagement.BoostState.Inactive;
|
|
146
|
-
// The implementation is responsible for setting the device accordingly with the cancelBoost command
|
|
147
|
-
// super.cancelBoost();
|
|
148
|
-
// cancelBoost is not implemented in matter.js
|
|
149
70
|
}
|
|
150
71
|
}
|
|
151
72
|
export class MatterbridgeWaterHeaterModeServer extends WaterHeaterModeServer {
|
|
@@ -163,4 +84,3 @@ export class MatterbridgeWaterHeaterModeServer extends WaterHeaterModeServer {
|
|
|
163
84
|
return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Success' };
|
|
164
85
|
}
|
|
165
86
|
}
|
|
166
|
-
//# sourceMappingURL=waterHeater.js.map
|
package/dist/dgram/coap.js
CHANGED
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description This file contains the class Coap.
|
|
3
|
-
* @file src/dgram/coap.ts
|
|
4
|
-
* @author Luca Liguori
|
|
5
|
-
* @created 2025-03-22
|
|
6
|
-
* @version 1.0.0
|
|
7
|
-
* @license Apache-2.0
|
|
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
|
-
// AnsiLogger imports
|
|
24
1
|
import { BLUE, db, GREEN, MAGENTA, nf } from 'node-ansi-logger';
|
|
25
|
-
// Net imports
|
|
26
2
|
import { COAP_MULTICAST_IPV4_ADDRESS, COAP_MULTICAST_PORT, Multicast } from './multicast.js';
|
|
27
3
|
export const COAP_OPTION_URI_PATH = 11;
|
|
28
4
|
export const COIOT_OPTION_DEVID = 3332;
|
|
@@ -48,26 +24,16 @@ export class Coap extends Multicast {
|
|
|
48
24
|
this.log.error(`Error decoding CoAP message: ${error instanceof Error ? error.message : error}`);
|
|
49
25
|
}
|
|
50
26
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Decodes a CoAP message from a Buffer.
|
|
53
|
-
*
|
|
54
|
-
* @param {Buffer} msg - The Buffer containing the raw CoAP message.
|
|
55
|
-
* @returns {CoapMessage} A parsed CoAP message object.
|
|
56
|
-
* @throws {Error} if the message is malformed.
|
|
57
|
-
*/
|
|
58
27
|
decodeCoapMessage(msg) {
|
|
59
|
-
// A valid CoAP message must have at least 4 bytes for the header.
|
|
60
28
|
if (msg.length < 4) {
|
|
61
29
|
throw new Error('Message too short to be a valid CoAP message');
|
|
62
30
|
}
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const messageId = msg.readUInt16BE(2); // 16-bit Message ID
|
|
31
|
+
const version = (msg[0] & 0xc0) >> 6;
|
|
32
|
+
const type = (msg[0] & 0x30) >> 4;
|
|
33
|
+
const tokenLength = msg[0] & 0x0f;
|
|
34
|
+
const code = msg[1];
|
|
35
|
+
const messageId = msg.readUInt16BE(2);
|
|
69
36
|
let offset = 4;
|
|
70
|
-
// Parse token if present.
|
|
71
37
|
let token = Buffer.alloc(0);
|
|
72
38
|
if (tokenLength > 0) {
|
|
73
39
|
if (msg.length < offset + tokenLength) {
|
|
@@ -76,20 +42,16 @@ export class Coap extends Multicast {
|
|
|
76
42
|
token = msg.slice(offset, offset + tokenLength);
|
|
77
43
|
offset += tokenLength;
|
|
78
44
|
}
|
|
79
|
-
// Parse options.
|
|
80
45
|
const options = [];
|
|
81
46
|
let currentOptionNumber = 0;
|
|
82
47
|
while (offset < msg.length) {
|
|
83
|
-
// Payload marker: 0xFF indicates the beginning of the payload.
|
|
84
48
|
if (msg[offset] === 0xff) {
|
|
85
|
-
offset++;
|
|
49
|
+
offset++;
|
|
86
50
|
break;
|
|
87
51
|
}
|
|
88
|
-
// Read the option header byte.
|
|
89
52
|
const optionHeader = msg[offset++];
|
|
90
|
-
let delta = (optionHeader & 0xf0) >> 4;
|
|
91
|
-
let length = optionHeader & 0x0f;
|
|
92
|
-
// Extended delta handling.
|
|
53
|
+
let delta = (optionHeader & 0xf0) >> 4;
|
|
54
|
+
let length = optionHeader & 0x0f;
|
|
93
55
|
if (delta === 13) {
|
|
94
56
|
if (offset >= msg.length) {
|
|
95
57
|
throw new Error('Invalid extended option delta');
|
|
@@ -106,7 +68,6 @@ export class Coap extends Multicast {
|
|
|
106
68
|
else if (delta === 15) {
|
|
107
69
|
throw new Error('Reserved option delta value encountered');
|
|
108
70
|
}
|
|
109
|
-
// Extended length handling.
|
|
110
71
|
if (length === 13) {
|
|
111
72
|
if (offset >= msg.length) {
|
|
112
73
|
throw new Error('Invalid extended option length');
|
|
@@ -123,9 +84,7 @@ export class Coap extends Multicast {
|
|
|
123
84
|
else if (length === 15) {
|
|
124
85
|
throw new Error('Reserved option length value encountered');
|
|
125
86
|
}
|
|
126
|
-
// Calculate the actual option number.
|
|
127
87
|
currentOptionNumber += delta;
|
|
128
|
-
// Ensure that the option's value fits in the remaining message.
|
|
129
88
|
if (offset + length > msg.length) {
|
|
130
89
|
throw new Error('Option length exceeds message length');
|
|
131
90
|
}
|
|
@@ -136,7 +95,6 @@ export class Coap extends Multicast {
|
|
|
136
95
|
value: optionValue,
|
|
137
96
|
});
|
|
138
97
|
}
|
|
139
|
-
// Parse payload if any remains.
|
|
140
98
|
const payload = offset < msg.length ? msg.slice(offset) : undefined;
|
|
141
99
|
return {
|
|
142
100
|
version,
|
|
@@ -149,38 +107,23 @@ export class Coap extends Multicast {
|
|
|
149
107
|
payload,
|
|
150
108
|
};
|
|
151
109
|
}
|
|
152
|
-
/**
|
|
153
|
-
* Encodes a CoAP message into a Buffer.
|
|
154
|
-
*
|
|
155
|
-
* @param {CoapMessage} msg - The CoAP message to encode.
|
|
156
|
-
* @returns {Buffer} A Buffer representing the encoded CoAP message.
|
|
157
|
-
* @throws {Error} if the message is malformed.
|
|
158
|
-
*/
|
|
159
110
|
encodeCoapMessage(msg) {
|
|
160
111
|
const parts = [];
|
|
161
|
-
// Determine token length (ensure it's consistent with msg.token)
|
|
162
112
|
const token = msg.token || Buffer.alloc(0);
|
|
163
113
|
const tokenLength = token.length;
|
|
164
114
|
if (tokenLength > 8) {
|
|
165
115
|
throw new Error('Token length cannot exceed 8 bytes');
|
|
166
116
|
}
|
|
167
|
-
// Create header (4 bytes):
|
|
168
|
-
// Byte 0: Version (2 bits), Type (2 bits), Token Length (4 bits)
|
|
169
|
-
// Byte 1: Code (8 bits)
|
|
170
|
-
// Bytes 2-3: Message ID (16 bits)
|
|
171
117
|
const header = Buffer.alloc(4);
|
|
172
118
|
header[0] = ((msg.version & 0x03) << 6) | ((msg.type & 0x03) << 4) | (tokenLength & 0x0f);
|
|
173
119
|
header[1] = msg.code;
|
|
174
120
|
header.writeUInt16BE(msg.messageId, 2);
|
|
175
121
|
parts.push(header);
|
|
176
|
-
// Append token if present.
|
|
177
122
|
if (tokenLength > 0) {
|
|
178
123
|
parts.push(token);
|
|
179
124
|
}
|
|
180
|
-
// Sort options by option number in ascending order.
|
|
181
125
|
const sortedOptions = msg.options.slice().sort((a, b) => a.number - b.number);
|
|
182
126
|
let previousOptionNumber = 0;
|
|
183
|
-
// Encode each option.
|
|
184
127
|
for (const option of sortedOptions) {
|
|
185
128
|
const optionDelta = option.number - previousOptionNumber;
|
|
186
129
|
const optionValueLength = option.value.length;
|
|
@@ -188,7 +131,6 @@ export class Coap extends Multicast {
|
|
|
188
131
|
let deltaExtended = null;
|
|
189
132
|
let lengthNibble;
|
|
190
133
|
let lengthExtended = null;
|
|
191
|
-
// Determine option delta nibble and extended delta field.
|
|
192
134
|
if (optionDelta < 13) {
|
|
193
135
|
deltaNibble = optionDelta;
|
|
194
136
|
}
|
|
@@ -201,7 +143,6 @@ export class Coap extends Multicast {
|
|
|
201
143
|
deltaExtended = Buffer.alloc(2);
|
|
202
144
|
deltaExtended.writeUInt16BE(optionDelta - 269, 0);
|
|
203
145
|
}
|
|
204
|
-
// Determine option length nibble and extended length field.
|
|
205
146
|
if (optionValueLength < 13) {
|
|
206
147
|
lengthNibble = optionValueLength;
|
|
207
148
|
}
|
|
@@ -214,42 +155,24 @@ export class Coap extends Multicast {
|
|
|
214
155
|
lengthExtended = Buffer.alloc(2);
|
|
215
156
|
lengthExtended.writeUInt16BE(optionValueLength - 269, 0);
|
|
216
157
|
}
|
|
217
|
-
// Option header byte: high nibble is delta, low nibble is length.
|
|
218
158
|
const optionHeader = Buffer.alloc(1);
|
|
219
159
|
optionHeader[0] = (deltaNibble << 4) | (lengthNibble & 0x0f);
|
|
220
160
|
parts.push(optionHeader);
|
|
221
|
-
// Append extended delta if needed.
|
|
222
161
|
if (deltaExtended) {
|
|
223
162
|
parts.push(deltaExtended);
|
|
224
163
|
}
|
|
225
|
-
// Append extended length if needed.
|
|
226
164
|
if (lengthExtended) {
|
|
227
165
|
parts.push(lengthExtended);
|
|
228
166
|
}
|
|
229
|
-
// Append the option value.
|
|
230
167
|
parts.push(option.value);
|
|
231
|
-
// Update previous option number.
|
|
232
168
|
previousOptionNumber = option.number;
|
|
233
169
|
}
|
|
234
|
-
// If a payload is present, add the payload marker (0xFF) followed by the payload.
|
|
235
170
|
if (msg.payload && msg.payload.length > 0) {
|
|
236
|
-
parts.push(Buffer.from([0xff]));
|
|
171
|
+
parts.push(Buffer.from([0xff]));
|
|
237
172
|
parts.push(msg.payload);
|
|
238
173
|
}
|
|
239
174
|
return Buffer.concat(parts);
|
|
240
175
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Converts a CoAP message type numeric value to its string representation.
|
|
243
|
-
*
|
|
244
|
-
* CoAP message types are:
|
|
245
|
-
* - 0: Confirmable (CON)
|
|
246
|
-
* - 1: Non-confirmable (NON)
|
|
247
|
-
* - 2: Acknowledgement (ACK)
|
|
248
|
-
* - 3: Reset (RST)
|
|
249
|
-
*
|
|
250
|
-
* @param {number} type - The numeric CoAP message type.
|
|
251
|
-
* @returns {string} The string representation of the message type.
|
|
252
|
-
*/
|
|
253
176
|
coapTypeToString(type) {
|
|
254
177
|
switch (type) {
|
|
255
178
|
case 0:
|
|
@@ -264,37 +187,18 @@ export class Coap extends Multicast {
|
|
|
264
187
|
return `Unknown Type (${type})`;
|
|
265
188
|
}
|
|
266
189
|
}
|
|
267
|
-
/**
|
|
268
|
-
* Converts a CoAP code numeric value to its string representation.
|
|
269
|
-
*
|
|
270
|
-
* The CoAP code is split into a 3-bit class and a 5-bit detail.
|
|
271
|
-
* For example:
|
|
272
|
-
* - 0.01: GET
|
|
273
|
-
* - 0.02: POST
|
|
274
|
-
* - 0.03: PUT
|
|
275
|
-
* - 0.04: DELETE
|
|
276
|
-
* - 2.05: Content (success response)
|
|
277
|
-
* - 4.04: Not Found (client error)
|
|
278
|
-
* - 5.00: Internal Server Error (server error)
|
|
279
|
-
*
|
|
280
|
-
* @param {number} code - The numeric CoAP code.
|
|
281
|
-
* @returns {string} The string representation of the code.
|
|
282
|
-
*/
|
|
283
190
|
coapCodeToString(code) {
|
|
284
|
-
// Split the code: the upper 3 bits form the class and the lower 5 bits form the detail.
|
|
285
191
|
const cls = code >> 5;
|
|
286
192
|
const detail = code & 0x1f;
|
|
287
193
|
const codeStr = `${cls}.${detail.toString().padStart(2, '0')}`;
|
|
288
194
|
return codeStr;
|
|
289
195
|
}
|
|
290
|
-
sendRequest(messageId, options,
|
|
291
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
292
|
-
payload, token, address, port) {
|
|
196
|
+
sendRequest(messageId, options, payload, token, address, port) {
|
|
293
197
|
const coapMessage = {
|
|
294
198
|
version: 1,
|
|
295
|
-
type: 1,
|
|
199
|
+
type: 1,
|
|
296
200
|
tokenLength: token ? Buffer.from(token).length : 0,
|
|
297
|
-
code: 1,
|
|
201
|
+
code: 1,
|
|
298
202
|
messageId,
|
|
299
203
|
token: token ? Buffer.from(token) : Buffer.alloc(0),
|
|
300
204
|
options,
|
|
@@ -313,10 +217,6 @@ export class Coap extends Multicast {
|
|
|
313
217
|
this.log.info(`Option: COAP_OPTION_URI_PATH => ${GREEN}${option.value}${nf}`);
|
|
314
218
|
}
|
|
315
219
|
else if (option.number === COIOT_OPTION_DEVID) {
|
|
316
|
-
/*
|
|
317
|
-
* First defined option is COIOT_OPTION_GLOBAL_DEVID. This is a global option and must be present in all CoIoT packages with request or payload.
|
|
318
|
-
* Its value is a string in format <devtype>#<devid>#<version> for example SHSEN-1#4B3F9E#1 The whole option should be less than 50 bytes.
|
|
319
|
-
*/
|
|
320
220
|
const parts = option.value.toString().split('#');
|
|
321
221
|
const deviceModel = parts[0];
|
|
322
222
|
const deviceMac = parts[1];
|
|
@@ -324,22 +224,10 @@ export class Coap extends Multicast {
|
|
|
324
224
|
this.log.info(`Option: COIOT_OPTION_DEVID => ${option.value} => Model: ${GREEN}${deviceModel}${nf}, MAC: ${GREEN}${deviceMac}${nf}, Protocol: ${GREEN}${protocolRevision}${nf}`);
|
|
325
225
|
}
|
|
326
226
|
else if (option.number === COIOT_OPTION_SERIAL) {
|
|
327
|
-
/*
|
|
328
|
-
* This option is mandatory in status response and publishes. It is a uint16_t in network byte order which indicates a change in the status report.
|
|
329
|
-
* When a new status report is handled, all payload processing can be skipped if the serial number does not change from the last processed payload.
|
|
330
|
-
* The value 0 is reserved and should not be sent. This allows easy initialization in the receiving devices.
|
|
331
|
-
*/
|
|
332
227
|
const serial = option.value.readUInt16BE(0);
|
|
333
228
|
this.log.info(`Option: COIOT_OPTION_SERIAL => 0x${option.value.toString('hex')} => serial: ${GREEN}${serial}${nf}`);
|
|
334
229
|
}
|
|
335
230
|
else if (option.number === COIOT_OPTION_VALIDITY) {
|
|
336
|
-
/*
|
|
337
|
-
* COIOT_OPTION_STATUS_VALIDITY is a uint16_t in network byte order (big endian) that states the maximal time between this and the next status publish.
|
|
338
|
-
* This way a device can state its report interval. If a report is not received from this device after the interval has passed the device should be considered offline.
|
|
339
|
-
* The LS bit of this option controls how the value is scaled:
|
|
340
|
-
* - If the LS bit is 0, the value is number of 1/10 of seconds in the validity period, so 2 is 0.2 seconds, 10 is a second, 600 is a minute, 65534 is 109 minutes and 13 seconds.
|
|
341
|
-
* - If the LS bit is 1, the value is number of 4 seconds interval in the whole interval. So 3 is 12 seconds, 11 is 44 seconds and 65535 is more than 3 days.
|
|
342
|
-
*/
|
|
343
231
|
const validity = option.value.readUInt16BE(0);
|
|
344
232
|
let validFor = 0;
|
|
345
233
|
if ((validity & 0x1) === 0) {
|
|
@@ -354,7 +242,7 @@ export class Coap extends Multicast {
|
|
|
354
242
|
this.log.info(`Option: ${option.number} - ${option.value
|
|
355
243
|
.toString('hex')
|
|
356
244
|
.match(/.{1,2}/g)
|
|
357
|
-
?.join(' ')}`);
|
|
245
|
+
?.join(' ')}`);
|
|
358
246
|
});
|
|
359
247
|
if (msg.payload && msg.payload.length > 0)
|
|
360
248
|
this.log.info(`Payload:`, JSON.parse(msg.payload.toString()), '\n');
|
|
@@ -362,4 +250,3 @@ export class Coap extends Multicast {
|
|
|
362
250
|
this.log.info(`No payload`, '\n');
|
|
363
251
|
}
|
|
364
252
|
}
|
|
365
|
-
//# sourceMappingURL=coap.js.map
|