matterbridge 3.4.0 → 3.4.1-dev-20251127-826b2bf
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 +128 -112
- package/README-DEV.md +2 -2
- package/README-DOCKER.md +1 -1
- package/README-MACOS-PLIST.md +1 -1
- package/README-NGINX.md +1 -1
- package/README-PODMAN.md +1 -1
- package/README-SERVICE-LOCAL.md +1 -1
- package/README-SERVICE-OPT.md +6 -1
- package/README-SERVICE.md +1 -1
- package/README.md +57 -49
- 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 -113
- package/dist/devices/airConditioner.js +0 -57
- package/dist/devices/batteryStorage.js +1 -48
- package/dist/devices/cooktop.js +0 -56
- package/dist/devices/dishwasher.js +0 -57
- package/dist/devices/evse.js +10 -74
- package/dist/devices/export.js +0 -5
- package/dist/devices/extractorHood.js +0 -43
- package/dist/devices/heatPump.js +2 -50
- package/dist/devices/laundryDryer.js +3 -62
- package/dist/devices/laundryWasher.js +4 -70
- package/dist/devices/microwaveOven.js +5 -88
- package/dist/devices/oven.js +0 -85
- package/dist/devices/refrigerator.js +0 -102
- package/dist/devices/roboticVacuumCleaner.js +9 -100
- package/dist/devices/solarPower.js +0 -38
- package/dist/devices/speaker.js +0 -84
- package/dist/devices/temperatureControl.js +3 -24
- package/dist/devices/waterHeater.js +2 -82
- 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 +35 -455
- package/dist/frontendTypes.js +0 -45
- package/dist/helpers.js +0 -53
- package/dist/index.js +0 -25
- package/dist/jestutils/export.js +0 -1
- package/dist/jestutils/jestHelpers.js +13 -352
- 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/matterNode.js +8 -369
- package/dist/matterbridge.js +74 -788
- package/dist/matterbridgeAccessoryPlatform.js +0 -38
- package/dist/matterbridgeBehaviors.js +5 -68
- package/dist/matterbridgeDeviceTypes.js +14 -635
- package/dist/matterbridgeDynamicPlatform.js +0 -38
- package/dist/matterbridgeEndpoint.js +53 -1444
- package/dist/matterbridgeEndpointHelpers.js +20 -483
- package/dist/matterbridgeEndpointTypes.js +0 -25
- package/dist/matterbridgePlatform.js +2 -460
- 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 +0 -37
- 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 +0 -41
- 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 +1 -71
- package/dist/utils/tracker.js +1 -64
- package/dist/utils/wait.js +8 -60
- package/frontend/build/assets/index.js +4 -4
- package/frontend/build/assets/vendor_mui.js +1 -1
- package/frontend/build/assets/vendor_node_modules.js +19 -83
- package/frontend/build/assets/vendor_qrcode.js +1 -9
- package/frontend/build/assets/vendor_rjsf.js +1 -9
- package/frontend/package-lock.json +229 -439
- package/frontend/package.json +15 -15
- package/marked.ps1 +15 -0
- package/npm-shrinkwrap.json +165 -231
- package/package.json +2 -3
- 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 -838
- 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 -135
- 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 -61
- 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 -34
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/jestutils/export.d.ts +0 -2
- package/dist/jestutils/export.d.ts.map +0 -1
- package/dist/jestutils/export.js.map +0 -1
- package/dist/jestutils/jestHelpers.d.ts +0 -303
- package/dist/jestutils/jestHelpers.d.ts.map +0 -1
- package/dist/jestutils/jestHelpers.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/matterNode.d.ts +0 -342
- package/dist/matterNode.d.ts.map +0 -1
- package/dist/matterNode.js.map +0 -1
- package/dist/matterbridge.d.ts +0 -473
- package/dist/matterbridge.d.ts.map +0 -1
- package/dist/matterbridge.js.map +0 -1
- package/dist/matterbridgeAccessoryPlatform.d.ts +0 -41
- 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 -698
- package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
- package/dist/matterbridgeDeviceTypes.js.map +0 -1
- package/dist/matterbridgeDynamicPlatform.d.ts +0 -41
- package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
- package/dist/matterbridgeDynamicPlatform.js.map +0 -1
- package/dist/matterbridgeEndpoint.d.ts +0 -1507
- package/dist/matterbridgeEndpoint.d.ts.map +0 -1
- package/dist/matterbridgeEndpoint.js.map +0 -1
- package/dist/matterbridgeEndpointHelpers.d.ts +0 -787
- package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
- package/dist/matterbridgeEndpointHelpers.js.map +0 -1
- package/dist/matterbridgeEndpointTypes.d.ts +0 -166
- package/dist/matterbridgeEndpointTypes.d.ts.map +0 -1
- package/dist/matterbridgeEndpointTypes.js.map +0 -1
- package/dist/matterbridgePlatform.d.ts +0 -524
- package/dist/matterbridgePlatform.d.ts.map +0 -1
- package/dist/matterbridgePlatform.js.map +0 -1
- package/dist/matterbridgeTypes.d.ts +0 -251
- 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 -35
- 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/network.d.ts +0 -111
- package/dist/utils/network.d.ts.map +0 -1
- package/dist/utils/network.js.map +0 -1
- package/dist/utils/spawn.d.ts +0 -33
- 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/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
|
package/dist/dgram/dgram.js
CHANGED
|
@@ -1,34 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description This file contains the class Dgram.
|
|
3
|
-
* @file dgram.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
|
-
// Node.js imports
|
|
24
1
|
import dgram from 'node:dgram';
|
|
25
2
|
import EventEmitter from 'node:events';
|
|
26
3
|
import os from 'node:os';
|
|
27
|
-
// AnsiLogger imports
|
|
28
4
|
import { AnsiLogger, BLUE, db, idn, nf, rs } from 'node-ansi-logger';
|
|
29
|
-
/**
|
|
30
|
-
* This class implements a dgram socket.
|
|
31
|
-
*/
|
|
32
5
|
export class Dgram extends EventEmitter {
|
|
33
6
|
log;
|
|
34
7
|
socket;
|
|
@@ -37,18 +10,9 @@ export class Dgram extends EventEmitter {
|
|
|
37
10
|
interfaceName;
|
|
38
11
|
interfaceAddress;
|
|
39
12
|
interfaceNetmask;
|
|
40
|
-
/**
|
|
41
|
-
* Creates an instance of Dgram.
|
|
42
|
-
*
|
|
43
|
-
* @param {string} name - The name of the socket.
|
|
44
|
-
* @param {'udp4' | 'udp6'} socketType - The type of the socket (IPv4 or IPv6).
|
|
45
|
-
* @param {boolean | undefined} reuseAddr - Whether to allow address reuse.
|
|
46
|
-
* @param {string} [interfaceName] - The name of the network interface to bind to.
|
|
47
|
-
* @param {string} [interfaceAddress] - The address of the network interface to bind to.
|
|
48
|
-
*/
|
|
49
13
|
constructor(name, socketType, reuseAddr = true, interfaceName, interfaceAddress) {
|
|
50
14
|
super();
|
|
51
|
-
this.log = new AnsiLogger({ logName: name, logTimestampFormat: 4
|
|
15
|
+
this.log = new AnsiLogger({ logName: name, logTimestampFormat: 4, logLevel: "debug" });
|
|
52
16
|
this.socket = dgram.createSocket({ type: socketType, reuseAddr });
|
|
53
17
|
this.socketType = socketType;
|
|
54
18
|
this.interfaceName = interfaceName;
|
|
@@ -82,13 +46,6 @@ export class Dgram extends EventEmitter {
|
|
|
82
46
|
this.onListening(address);
|
|
83
47
|
});
|
|
84
48
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Sends a message to the specified server.
|
|
87
|
-
*
|
|
88
|
-
* @param {Buffer} msg - The message buffer to send.
|
|
89
|
-
* @param {string} serverAddress - The IPv4 address of the destination server.
|
|
90
|
-
* @param {number} serverPort - The port of the destination server.
|
|
91
|
-
*/
|
|
92
49
|
send(msg, serverAddress, serverPort) {
|
|
93
50
|
this.socket.send(msg, 0, msg.length, serverPort, serverAddress, (error) => {
|
|
94
51
|
if (error) {
|
|
@@ -126,30 +83,18 @@ export class Dgram extends EventEmitter {
|
|
|
126
83
|
this.log.info(`Socket ready on ${BLUE}${address.family}${nf} ${BLUE}${address.address}${nf}:${BLUE}${address.port}${nf}`);
|
|
127
84
|
this.emit('ready', address);
|
|
128
85
|
}
|
|
129
|
-
/**
|
|
130
|
-
* Retrieves the IPv4 address of the specified network interface or the first external IPv4 interface if no interface is specified.
|
|
131
|
-
* Throws an error if no suitable interface or address is found.
|
|
132
|
-
*
|
|
133
|
-
* @param {string} networkInterface - The name of the network interface to retrieve the IPv4 address from. If not specified, the first external IPv4 interface will be used.
|
|
134
|
-
* @returns {string | undefined} The IPv4 address of the specified network interface or the first external IPv4 interface.
|
|
135
|
-
* @throws {Error} if no suitable interface or address is found.
|
|
136
|
-
*/
|
|
137
86
|
getIpv4InterfaceAddress(networkInterface) {
|
|
138
|
-
// Normalize the interface name: treat an empty string as undefined.
|
|
139
87
|
if (networkInterface === '')
|
|
140
88
|
networkInterface = undefined;
|
|
141
89
|
const interfaces = os.networkInterfaces();
|
|
142
|
-
// If a specific interface is provided but not found, warn and fall back.
|
|
143
90
|
if (networkInterface && !interfaces[networkInterface]) {
|
|
144
91
|
this.log.warn(`Interface "${networkInterface}" not found. Using first external IPv4 interface.`);
|
|
145
92
|
networkInterface = undefined;
|
|
146
93
|
}
|
|
147
|
-
// If no interface was specified or the provided one doesn't exist, find the first external IPv4 interface.
|
|
148
94
|
if (!networkInterface) {
|
|
149
95
|
for (const [interfaceName, interfaceDetails] of Object.entries(interfaces)) {
|
|
150
96
|
if (!interfaceDetails)
|
|
151
97
|
continue;
|
|
152
|
-
// Check if at least one external IPv4 address exists on this interface.
|
|
153
98
|
for (const detail of interfaceDetails) {
|
|
154
99
|
if (detail.family === 'IPv4' && !detail.internal) {
|
|
155
100
|
networkInterface = interfaceName;
|
|
@@ -163,7 +108,6 @@ export class Dgram extends EventEmitter {
|
|
|
163
108
|
if (!networkInterface) {
|
|
164
109
|
throw new Error(`Didn't find an external IPv4 network interface`);
|
|
165
110
|
}
|
|
166
|
-
// Select the first external IPv4 address from the interface.
|
|
167
111
|
const addresses = interfaces[networkInterface];
|
|
168
112
|
const ipv4Address = addresses?.find((addr) => addr.family === 'IPv4' && !addr.internal);
|
|
169
113
|
if (!ipv4Address) {
|
|
@@ -171,25 +115,14 @@ export class Dgram extends EventEmitter {
|
|
|
171
115
|
}
|
|
172
116
|
return ipv4Address.address;
|
|
173
117
|
}
|
|
174
|
-
/**
|
|
175
|
-
* Retrieves the IPv6 address of the specified network interface or the first external IPv6 interface if no interface is specified.
|
|
176
|
-
* Throws an error if no suitable interface or address is found.
|
|
177
|
-
*
|
|
178
|
-
* @param {string} [networkInterface] - The name of the network interface to retrieve the IPv6 address from. If not specified, the first external IPv6 interface will be used.
|
|
179
|
-
* @returns {string | undefined} The IPv6 address of the specified network interface or the first external IPv6 interface.
|
|
180
|
-
* @throws {Error} If no suitable interface or address is found.
|
|
181
|
-
*/
|
|
182
118
|
getIpv6InterfaceAddress(networkInterface) {
|
|
183
|
-
// Normalize the interface name: treat an empty string as undefined.
|
|
184
119
|
if (networkInterface === '')
|
|
185
120
|
networkInterface = undefined;
|
|
186
121
|
const interfaces = os.networkInterfaces();
|
|
187
|
-
// If a specific interface is provided, verify it exists. Otherwise, warn and use the first external IPv6 interface.
|
|
188
122
|
if (networkInterface && !interfaces[networkInterface]) {
|
|
189
123
|
this.log.warn(`Interface "${networkInterface}" not found. Using first external IPv6 interface.`);
|
|
190
124
|
networkInterface = undefined;
|
|
191
125
|
}
|
|
192
|
-
// If no network interface was specified, search for the first external IPv6 interface.
|
|
193
126
|
if (!networkInterface) {
|
|
194
127
|
for (const [interfaceName, interfaceDetails] of Object.entries(interfaces)) {
|
|
195
128
|
if (!interfaceDetails)
|
|
@@ -208,21 +141,18 @@ export class Dgram extends EventEmitter {
|
|
|
208
141
|
throw new Error(`Didn't find an external IPv6 network interface`);
|
|
209
142
|
}
|
|
210
143
|
const addresses = interfaces[networkInterface];
|
|
211
|
-
// Try to find a link-local address and use scopeid
|
|
212
144
|
const linkLocalAddress = addresses?.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.address.startsWith('fe80'));
|
|
213
145
|
if (linkLocalAddress) {
|
|
214
146
|
this.log.debug('Found IPv6 link-local address');
|
|
215
147
|
return linkLocalAddress.scopeid ? `${linkLocalAddress.address}%${process.platform !== 'win32' ? networkInterface : linkLocalAddress.scopeid}` : linkLocalAddress.address;
|
|
216
148
|
}
|
|
217
149
|
this.log.debug('No IPv6 link-local address found');
|
|
218
|
-
// Try to find a unique local address
|
|
219
150
|
const ulaAddress = addresses?.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.address.startsWith('fd') && addr.netmask === 'ffff:ffff:ffff:ffff::');
|
|
220
151
|
if (ulaAddress) {
|
|
221
152
|
this.log.debug('Found IPv6 Unique Local Addresses (ULA) unicast address');
|
|
222
153
|
return ulaAddress.address;
|
|
223
154
|
}
|
|
224
155
|
this.log.debug('No IPv6 Unique Local Addresses (ULA) unicast address found');
|
|
225
|
-
// Try to find a unique local address
|
|
226
156
|
const uniqueLocalAddress = addresses?.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.address.startsWith('fd'));
|
|
227
157
|
if (uniqueLocalAddress) {
|
|
228
158
|
this.log.debug('Found IPv6 Unique Local Addresses (ULA) address');
|
|
@@ -231,11 +161,6 @@ export class Dgram extends EventEmitter {
|
|
|
231
161
|
this.log.debug('No IPv6 Unique Local Addresses (ULA) address found');
|
|
232
162
|
throw new Error(`Interface ${networkInterface} does not have a suitable external IPv6 address`);
|
|
233
163
|
}
|
|
234
|
-
/**
|
|
235
|
-
* Retrieves the names of all available network interfaces.
|
|
236
|
-
*
|
|
237
|
-
* @returns {string[]} An array of network interface names.
|
|
238
|
-
*/
|
|
239
164
|
getInterfacesNames() {
|
|
240
165
|
const interfaces = os.networkInterfaces();
|
|
241
166
|
const interfaceNames = [];
|
|
@@ -246,12 +171,6 @@ export class Dgram extends EventEmitter {
|
|
|
246
171
|
}
|
|
247
172
|
return interfaceNames;
|
|
248
173
|
}
|
|
249
|
-
/**
|
|
250
|
-
* Retrieves the scope ID of the first found IPv6 address on the specified network interface or on any interface if none is specified.
|
|
251
|
-
*
|
|
252
|
-
* @param {string} [interfaceName] - The name of the network interface. If not provided, the first found IPv6 address will be used.
|
|
253
|
-
* @returns {string} The scope ID of the first found IPv6 address or an empty string.
|
|
254
|
-
*/
|
|
255
174
|
getIpv6ScopeId(interfaceName) {
|
|
256
175
|
const interfaces = os.networkInterfaces();
|
|
257
176
|
for (const name in interfaces) {
|
|
@@ -261,24 +180,17 @@ export class Dgram extends EventEmitter {
|
|
|
261
180
|
if (iface) {
|
|
262
181
|
const ipv6Address = iface.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.scopeid);
|
|
263
182
|
if (ipv6Address) {
|
|
264
|
-
return process.platform === 'win32' ? '%' + String(ipv6Address.scopeid) : '%' + name;
|
|
183
|
+
return process.platform === 'win32' ? '%' + String(ipv6Address.scopeid) : '%' + name;
|
|
265
184
|
}
|
|
266
185
|
}
|
|
267
186
|
}
|
|
268
187
|
return '';
|
|
269
188
|
}
|
|
270
|
-
/**
|
|
271
|
-
* Retrieves the interface name from the scope id of an IPv6 address.
|
|
272
|
-
*
|
|
273
|
-
* @param {number} scopeId - The scope id of the IPv6 address.
|
|
274
|
-
* @returns {string | undefined} The interface name or undefined if not found.
|
|
275
|
-
*/
|
|
276
189
|
getInterfaceNameFromScopeId(scopeId) {
|
|
277
190
|
const nets = os.networkInterfaces();
|
|
278
191
|
for (const ifaceName in nets) {
|
|
279
192
|
const addresses = nets[ifaceName] || [];
|
|
280
193
|
for (const addr of addresses) {
|
|
281
|
-
// Check for IPv6 addresses with a matching scope id.
|
|
282
194
|
if (addr.family === 'IPv6' && addr.scopeid === scopeId) {
|
|
283
195
|
return ifaceName;
|
|
284
196
|
}
|
|
@@ -286,16 +198,8 @@ export class Dgram extends EventEmitter {
|
|
|
286
198
|
}
|
|
287
199
|
return undefined;
|
|
288
200
|
}
|
|
289
|
-
/**
|
|
290
|
-
* Retrieves the netmask of the specified interface address.
|
|
291
|
-
*
|
|
292
|
-
* @param {string} interfaceAddress - The interface address for which to retrieve the netmask.
|
|
293
|
-
* @returns {string | undefined} The netmask of the specified interface address or undefined if not found.
|
|
294
|
-
*/
|
|
295
201
|
getNetmask(interfaceAddress) {
|
|
296
|
-
// Remove zone index if present (e.g. for IPv6 "fe80::1%eth0")
|
|
297
202
|
const cleanedAddress = interfaceAddress.includes('%') ? interfaceAddress.split('%')[0] : interfaceAddress;
|
|
298
|
-
// Iterate over all interfaces.
|
|
299
203
|
const nets = os.networkInterfaces();
|
|
300
204
|
for (const ifaceName in nets) {
|
|
301
205
|
const ifaceAddresses = nets[ifaceName];
|
|
@@ -309,13 +213,6 @@ export class Dgram extends EventEmitter {
|
|
|
309
213
|
}
|
|
310
214
|
return undefined;
|
|
311
215
|
}
|
|
312
|
-
/**
|
|
313
|
-
* Computes the broadcast address given an IPv4 address and netmask.
|
|
314
|
-
*
|
|
315
|
-
* @param {string | undefined} [ipAddress] - The IPv4 address e.g. "192.168.1.20"
|
|
316
|
-
* @param {string | undefined} [netmask] - The IPv4 netmask e.g. "255.255.255.0"
|
|
317
|
-
* @returns {string | undefined} The computed broadcast address, e.g. "192.168.1.255"
|
|
318
|
-
*/
|
|
319
216
|
getIpv4BroadcastAddress(ipAddress, netmask) {
|
|
320
217
|
if (!ipAddress || !netmask) {
|
|
321
218
|
return undefined;
|
|
@@ -325,17 +222,9 @@ export class Dgram extends EventEmitter {
|
|
|
325
222
|
const broadcastParts = ipParts.map((octet, i) => (octet & maskParts[i]) | (255 - maskParts[i]));
|
|
326
223
|
return broadcastParts.join('.');
|
|
327
224
|
}
|
|
328
|
-
/**
|
|
329
|
-
* Returns the broadcast IPv6 address.
|
|
330
|
-
*
|
|
331
|
-
* @returns {string} The broadcast IPv6 address, e.g. "ff02::1"
|
|
332
|
-
*/
|
|
333
225
|
getIpv6BroadcastAddress() {
|
|
334
226
|
return 'ff02::1';
|
|
335
227
|
}
|
|
336
|
-
/**
|
|
337
|
-
* Logs all available network interfaces and their details.
|
|
338
|
-
*/
|
|
339
228
|
listNetworkInterfaces() {
|
|
340
229
|
const interfaces = os.networkInterfaces();
|
|
341
230
|
for (const [name, addresses] of Object.entries(interfaces)) {
|
|
@@ -348,4 +237,3 @@ export class Dgram extends EventEmitter {
|
|
|
348
237
|
}
|
|
349
238
|
}
|
|
350
239
|
}
|
|
351
|
-
//# sourceMappingURL=dgram.js.map
|
package/dist/dgram/mb_coap.js
CHANGED
|
@@ -1,65 +1,28 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description This file contains the bin mb_coap for the class Coap.
|
|
3
|
-
* @file src/dgram/mb_coap.ts
|
|
4
|
-
* @author Luca Liguori
|
|
5
|
-
* @created 2025-07-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
|
-
// Net imports
|
|
24
1
|
import { COAP_MULTICAST_IPV4_ADDRESS, COAP_MULTICAST_IPV6_ADDRESS, COAP_MULTICAST_PORT } from './multicast.js';
|
|
25
2
|
import { Coap, COAP_OPTION_URI_PATH } from './coap.js';
|
|
26
|
-
// istanbul ignore next
|
|
27
3
|
{
|
|
28
4
|
const coapIpv4 = new Coap('CoAP Server udp4', COAP_MULTICAST_IPV4_ADDRESS, COAP_MULTICAST_PORT, 'udp4', true);
|
|
29
5
|
const coapIpv6 = new Coap('CoAP Server udp6', COAP_MULTICAST_IPV6_ADDRESS, COAP_MULTICAST_PORT, 'udp6', true);
|
|
30
6
|
coapIpv4.listNetworkInterfaces();
|
|
31
|
-
/**
|
|
32
|
-
* Cleanup and log device information before exiting.
|
|
33
|
-
*/
|
|
34
7
|
function cleanupAndLogAndExit() {
|
|
35
8
|
if (process.argv.includes('--coap-udp4'))
|
|
36
9
|
coapIpv4.stop();
|
|
37
10
|
if (process.argv.includes('--coap-udp6'))
|
|
38
11
|
coapIpv6.stop();
|
|
39
|
-
// eslint-disable-next-line n/no-process-exit
|
|
40
12
|
process.exit(0);
|
|
41
13
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Queries mDNS services over UDP IPv4 and sends a response for a specific service instance.
|
|
44
|
-
* This function sends a query for Shelly, HTTP, and services, and responds with the appropriate PTR records.
|
|
45
|
-
*/
|
|
46
14
|
const requestUdp4 = () => {
|
|
47
15
|
coapIpv4.sendRequest(32000, [
|
|
48
16
|
{ number: COAP_OPTION_URI_PATH, value: Buffer.from('cit') },
|
|
49
17
|
{ number: COAP_OPTION_URI_PATH, value: Buffer.from('d') },
|
|
50
18
|
], {}, undefined, COAP_MULTICAST_IPV4_ADDRESS, COAP_MULTICAST_PORT);
|
|
51
19
|
};
|
|
52
|
-
/**
|
|
53
|
-
* Queries mDNS services over UDP IPv4 and sends a response for a specific service instance.
|
|
54
|
-
* This function sends a query for Shelly, HTTP, and services, and responds with the appropriate PTR records.
|
|
55
|
-
*/
|
|
56
20
|
const requestUdp6 = () => {
|
|
57
21
|
coapIpv6.sendRequest(32000, [
|
|
58
22
|
{ number: COAP_OPTION_URI_PATH, value: Buffer.from('cit') },
|
|
59
23
|
{ number: COAP_OPTION_URI_PATH, value: Buffer.from('d') },
|
|
60
24
|
], {}, undefined, COAP_MULTICAST_IPV6_ADDRESS, COAP_MULTICAST_PORT);
|
|
61
25
|
};
|
|
62
|
-
// Handle Ctrl+C (SIGINT) to stop and log devices
|
|
63
26
|
process.on('SIGINT', () => {
|
|
64
27
|
cleanupAndLogAndExit();
|
|
65
28
|
});
|
|
@@ -67,7 +30,7 @@ import { Coap, COAP_OPTION_URI_PATH } from './coap.js';
|
|
|
67
30
|
coapIpv4.on('ready', (address) => {
|
|
68
31
|
coapIpv4.log.info(`coapIpv4 server ready on ${address.family} ${address.address}:${address.port}`);
|
|
69
32
|
if (!process.argv.includes('--coap-request'))
|
|
70
|
-
return;
|
|
33
|
+
return;
|
|
71
34
|
requestUdp4();
|
|
72
35
|
setInterval(() => {
|
|
73
36
|
requestUdp4();
|
|
@@ -77,7 +40,7 @@ import { Coap, COAP_OPTION_URI_PATH } from './coap.js';
|
|
|
77
40
|
coapIpv6.on('ready', (address) => {
|
|
78
41
|
coapIpv6.log.info(`coapIpv6 server ready on ${address.family} ${address.address}:${address.port}`);
|
|
79
42
|
if (!process.argv.includes('--coap-request'))
|
|
80
|
-
return;
|
|
43
|
+
return;
|
|
81
44
|
requestUdp6();
|
|
82
45
|
setInterval(() => {
|
|
83
46
|
requestUdp6();
|
|
@@ -85,6 +48,5 @@ import { Coap, COAP_OPTION_URI_PATH } from './coap.js';
|
|
|
85
48
|
});
|
|
86
49
|
setTimeout(() => {
|
|
87
50
|
cleanupAndLogAndExit();
|
|
88
|
-
}, 600000);
|
|
51
|
+
}, 600000);
|
|
89
52
|
}
|
|
90
|
-
//# sourceMappingURL=mb_coap.js.map
|