matterbridge 3.1.6-dev-20250720-88d6141 → 3.1.6

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.
Files changed (236) hide show
  1. package/CHANGELOG.md +6 -4
  2. package/README-DOCKER.md +35 -0
  3. package/dist/cli.d.ts +26 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +91 -2
  6. package/dist/cli.js.map +1 -0
  7. package/dist/cliEmitter.d.ts +34 -0
  8. package/dist/cliEmitter.d.ts.map +1 -0
  9. package/dist/cliEmitter.js +30 -0
  10. package/dist/cliEmitter.js.map +1 -0
  11. package/dist/clusters/export.d.ts +2 -0
  12. package/dist/clusters/export.d.ts.map +1 -0
  13. package/dist/clusters/export.js +2 -0
  14. package/dist/clusters/export.js.map +1 -0
  15. package/dist/defaultConfigSchema.d.ts +28 -0
  16. package/dist/defaultConfigSchema.d.ts.map +1 -0
  17. package/dist/defaultConfigSchema.js +24 -0
  18. package/dist/defaultConfigSchema.js.map +1 -0
  19. package/dist/deviceManager.d.ts +112 -0
  20. package/dist/deviceManager.d.ts.map +1 -0
  21. package/dist/deviceManager.js +94 -1
  22. package/dist/deviceManager.js.map +1 -0
  23. package/dist/devices/batteryStorage.d.ts +48 -0
  24. package/dist/devices/batteryStorage.d.ts.map +1 -0
  25. package/dist/devices/batteryStorage.js +48 -1
  26. package/dist/devices/batteryStorage.js.map +1 -0
  27. package/dist/devices/dishwasher.d.ts +91 -0
  28. package/dist/devices/dishwasher.d.ts.map +1 -0
  29. package/dist/devices/dishwasher.js +78 -3
  30. package/dist/devices/dishwasher.js.map +1 -0
  31. package/dist/devices/evse.d.ts +75 -0
  32. package/dist/devices/evse.d.ts.map +1 -0
  33. package/dist/devices/evse.js +74 -10
  34. package/dist/devices/evse.js.map +1 -0
  35. package/dist/devices/export.d.ts +11 -0
  36. package/dist/devices/export.d.ts.map +1 -0
  37. package/dist/devices/export.js +2 -0
  38. package/dist/devices/export.js.map +1 -0
  39. package/dist/devices/extractorHood.d.ts +46 -0
  40. package/dist/devices/extractorHood.d.ts.map +1 -0
  41. package/dist/devices/extractorHood.js +42 -0
  42. package/dist/devices/extractorHood.js.map +1 -0
  43. package/dist/devices/heatPump.d.ts +47 -0
  44. package/dist/devices/heatPump.d.ts.map +1 -0
  45. package/dist/devices/heatPump.js +50 -2
  46. package/dist/devices/heatPump.js.map +1 -0
  47. package/dist/devices/laundryDryer.d.ts +87 -0
  48. package/dist/devices/laundryDryer.d.ts.map +1 -0
  49. package/dist/devices/laundryDryer.js +83 -6
  50. package/dist/devices/laundryDryer.js.map +1 -0
  51. package/dist/devices/laundryWasher.d.ts +242 -0
  52. package/dist/devices/laundryWasher.d.ts.map +1 -0
  53. package/dist/devices/laundryWasher.js +91 -7
  54. package/dist/devices/laundryWasher.js.map +1 -0
  55. package/dist/devices/roboticVacuumCleaner.d.ts +112 -0
  56. package/dist/devices/roboticVacuumCleaner.d.ts.map +1 -0
  57. package/dist/devices/roboticVacuumCleaner.js +93 -7
  58. package/dist/devices/roboticVacuumCleaner.js.map +1 -0
  59. package/dist/devices/solarPower.d.ts +40 -0
  60. package/dist/devices/solarPower.d.ts.map +1 -0
  61. package/dist/devices/solarPower.js +38 -0
  62. package/dist/devices/solarPower.js.map +1 -0
  63. package/dist/devices/waterHeater.d.ts +111 -0
  64. package/dist/devices/waterHeater.d.ts.map +1 -0
  65. package/dist/devices/waterHeater.js +82 -2
  66. package/dist/devices/waterHeater.js.map +1 -0
  67. package/dist/dgram/dgram.d.ts +140 -0
  68. package/dist/dgram/dgram.d.ts.map +1 -0
  69. package/dist/dgram/dgram.js +348 -0
  70. package/dist/dgram/dgram.js.map +1 -0
  71. package/dist/dgram/mdns.d.ts +288 -0
  72. package/dist/dgram/mdns.d.ts.map +1 -0
  73. package/dist/dgram/mdns.js +840 -0
  74. package/dist/dgram/mdns.js.map +1 -0
  75. package/dist/dgram/multicast.d.ts +65 -0
  76. package/dist/dgram/multicast.d.ts.map +1 -0
  77. package/dist/dgram/multicast.js +170 -0
  78. package/dist/dgram/multicast.js.map +1 -0
  79. package/dist/dgram/unicast.d.ts +56 -0
  80. package/dist/dgram/unicast.d.ts.map +1 -0
  81. package/dist/dgram/unicast.js +91 -0
  82. package/dist/dgram/unicast.js.map +1 -0
  83. package/dist/frontend.d.ts +304 -0
  84. package/dist/frontend.d.ts.map +1 -0
  85. package/dist/frontend.js +435 -21
  86. package/dist/frontend.js.map +1 -0
  87. package/dist/globalMatterbridge.d.ts +59 -0
  88. package/dist/globalMatterbridge.d.ts.map +1 -0
  89. package/dist/globalMatterbridge.js +47 -0
  90. package/dist/globalMatterbridge.js.map +1 -0
  91. package/dist/helpers.d.ts +48 -0
  92. package/dist/helpers.d.ts.map +1 -0
  93. package/dist/helpers.js +53 -0
  94. package/dist/helpers.js.map +1 -0
  95. package/dist/index.d.ts +33 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +30 -1
  98. package/dist/index.js.map +1 -0
  99. package/dist/logger/export.d.ts +2 -0
  100. package/dist/logger/export.d.ts.map +1 -0
  101. package/dist/logger/export.js +1 -0
  102. package/dist/logger/export.js.map +1 -0
  103. package/dist/matter/behaviors.d.ts +2 -0
  104. package/dist/matter/behaviors.d.ts.map +1 -0
  105. package/dist/matter/behaviors.js +2 -0
  106. package/dist/matter/behaviors.js.map +1 -0
  107. package/dist/matter/clusters.d.ts +2 -0
  108. package/dist/matter/clusters.d.ts.map +1 -0
  109. package/dist/matter/clusters.js +2 -0
  110. package/dist/matter/clusters.js.map +1 -0
  111. package/dist/matter/devices.d.ts +2 -0
  112. package/dist/matter/devices.d.ts.map +1 -0
  113. package/dist/matter/devices.js +2 -0
  114. package/dist/matter/devices.js.map +1 -0
  115. package/dist/matter/endpoints.d.ts +2 -0
  116. package/dist/matter/endpoints.d.ts.map +1 -0
  117. package/dist/matter/endpoints.js +2 -0
  118. package/dist/matter/endpoints.js.map +1 -0
  119. package/dist/matter/export.d.ts +5 -0
  120. package/dist/matter/export.d.ts.map +1 -0
  121. package/dist/matter/export.js +3 -0
  122. package/dist/matter/export.js.map +1 -0
  123. package/dist/matter/types.d.ts +3 -0
  124. package/dist/matter/types.d.ts.map +1 -0
  125. package/dist/matter/types.js +3 -0
  126. package/dist/matter/types.js.map +1 -0
  127. package/dist/matterbridge.d.ts +460 -0
  128. package/dist/matterbridge.d.ts.map +1 -0
  129. package/dist/matterbridge.js +810 -52
  130. package/dist/matterbridge.js.map +1 -0
  131. package/dist/matterbridgeAccessoryPlatform.d.ts +42 -0
  132. package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
  133. package/dist/matterbridgeAccessoryPlatform.js +36 -0
  134. package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
  135. package/dist/matterbridgeBehaviors.d.ts +1351 -0
  136. package/dist/matterbridgeBehaviors.d.ts.map +1 -0
  137. package/dist/matterbridgeBehaviors.js +68 -5
  138. package/dist/matterbridgeBehaviors.js.map +1 -0
  139. package/dist/matterbridgeDeviceTypes.d.ts +709 -0
  140. package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
  141. package/dist/matterbridgeDeviceTypes.js +579 -15
  142. package/dist/matterbridgeDeviceTypes.js.map +1 -0
  143. package/dist/matterbridgeDynamicPlatform.d.ts +42 -0
  144. package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
  145. package/dist/matterbridgeDynamicPlatform.js +36 -0
  146. package/dist/matterbridgeDynamicPlatform.js.map +1 -0
  147. package/dist/matterbridgeEndpoint.d.ts +1328 -0
  148. package/dist/matterbridgeEndpoint.d.ts.map +1 -0
  149. package/dist/matterbridgeEndpoint.js +1200 -43
  150. package/dist/matterbridgeEndpoint.js.map +1 -0
  151. package/dist/matterbridgeEndpointHelpers.d.ts +3198 -0
  152. package/dist/matterbridgeEndpointHelpers.d.ts.map +1 -0
  153. package/dist/matterbridgeEndpointHelpers.js +322 -12
  154. package/dist/matterbridgeEndpointHelpers.js.map +1 -0
  155. package/dist/matterbridgePlatform.d.ts +310 -0
  156. package/dist/matterbridgePlatform.d.ts.map +1 -0
  157. package/dist/matterbridgePlatform.js +233 -0
  158. package/dist/matterbridgePlatform.js.map +1 -0
  159. package/dist/matterbridgeTypes.d.ts +195 -0
  160. package/dist/matterbridgeTypes.d.ts.map +1 -0
  161. package/dist/matterbridgeTypes.js +25 -0
  162. package/dist/matterbridgeTypes.js.map +1 -0
  163. package/dist/pluginManager.d.ts +270 -0
  164. package/dist/pluginManager.d.ts.map +1 -0
  165. package/dist/pluginManager.js +249 -3
  166. package/dist/pluginManager.js.map +1 -0
  167. package/dist/shelly.d.ts +174 -0
  168. package/dist/shelly.d.ts.map +1 -0
  169. package/dist/shelly.js +168 -7
  170. package/dist/shelly.js.map +1 -0
  171. package/dist/storage/export.d.ts +2 -0
  172. package/dist/storage/export.d.ts.map +1 -0
  173. package/dist/storage/export.js +1 -0
  174. package/dist/storage/export.js.map +1 -0
  175. package/dist/update.d.ts +59 -0
  176. package/dist/update.d.ts.map +1 -0
  177. package/dist/update.js +54 -0
  178. package/dist/update.js.map +1 -0
  179. package/dist/utils/colorUtils.d.ts +117 -0
  180. package/dist/utils/colorUtils.d.ts.map +1 -0
  181. package/dist/utils/colorUtils.js +263 -2
  182. package/dist/utils/colorUtils.js.map +1 -0
  183. package/dist/utils/commandLine.d.ts +59 -0
  184. package/dist/utils/commandLine.d.ts.map +1 -0
  185. package/dist/utils/commandLine.js +54 -0
  186. package/dist/utils/commandLine.js.map +1 -0
  187. package/dist/utils/copyDirectory.d.ts +33 -0
  188. package/dist/utils/copyDirectory.d.ts.map +1 -0
  189. package/dist/utils/copyDirectory.js +38 -1
  190. package/dist/utils/copyDirectory.js.map +1 -0
  191. package/dist/utils/createDirectory.d.ts +34 -0
  192. package/dist/utils/createDirectory.d.ts.map +1 -0
  193. package/dist/utils/createDirectory.js +33 -0
  194. package/dist/utils/createDirectory.js.map +1 -0
  195. package/dist/utils/createZip.d.ts +39 -0
  196. package/dist/utils/createZip.d.ts.map +1 -0
  197. package/dist/utils/createZip.js +47 -2
  198. package/dist/utils/createZip.js.map +1 -0
  199. package/dist/utils/deepCopy.d.ts +32 -0
  200. package/dist/utils/deepCopy.d.ts.map +1 -0
  201. package/dist/utils/deepCopy.js +39 -0
  202. package/dist/utils/deepCopy.js.map +1 -0
  203. package/dist/utils/deepEqual.d.ts +54 -0
  204. package/dist/utils/deepEqual.d.ts.map +1 -0
  205. package/dist/utils/deepEqual.js +72 -1
  206. package/dist/utils/deepEqual.js.map +1 -0
  207. package/dist/utils/error.d.ts +44 -0
  208. package/dist/utils/error.d.ts.map +1 -0
  209. package/dist/utils/error.js +41 -0
  210. package/dist/utils/error.js.map +1 -0
  211. package/dist/utils/export.d.ts +12 -0
  212. package/dist/utils/export.d.ts.map +1 -0
  213. package/dist/utils/export.js +1 -0
  214. package/dist/utils/export.js.map +1 -0
  215. package/dist/utils/hex.d.ts +49 -0
  216. package/dist/utils/hex.d.ts.map +1 -0
  217. package/dist/utils/hex.js +58 -0
  218. package/dist/utils/hex.js.map +1 -0
  219. package/dist/utils/isvalid.d.ts +103 -0
  220. package/dist/utils/isvalid.d.ts.map +1 -0
  221. package/dist/utils/isvalid.js +101 -0
  222. package/dist/utils/isvalid.js.map +1 -0
  223. package/dist/utils/network.d.ts +74 -0
  224. package/dist/utils/network.d.ts.map +1 -0
  225. package/dist/utils/network.js +81 -5
  226. package/dist/utils/network.js.map +1 -0
  227. package/dist/utils/spawn.d.ts +33 -0
  228. package/dist/utils/spawn.d.ts.map +1 -0
  229. package/dist/utils/spawn.js +40 -0
  230. package/dist/utils/spawn.js.map +1 -0
  231. package/dist/utils/wait.d.ts +56 -0
  232. package/dist/utils/wait.d.ts.map +1 -0
  233. package/dist/utils/wait.js +62 -9
  234. package/dist/utils/wait.js.map +1 -0
  235. package/npm-shrinkwrap.json +2 -2
  236. package/package.json +2 -1
@@ -1,3 +1,26 @@
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
+ */
1
24
  import { ModeBase } from '@matter/main/clusters/mode-base';
2
25
  import { WaterHeaterManagement } from '@matter/main/clusters/water-heater-management';
3
26
  import { WaterHeaterMode } from '@matter/main/clusters/water-heater-mode';
@@ -8,6 +31,29 @@ import { MatterbridgeServer } from '../matterbridgeBehaviors.js';
8
31
  import { electricalSensor, powerSource, waterHeater } from '../matterbridgeDeviceTypes.js';
9
32
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
10
33
  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
+ */
11
57
  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) {
12
58
  super([waterHeater, powerSource, electricalSensor], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
13
59
  this.createDefaultIdentifyClusterServer()
@@ -22,15 +68,42 @@ export class WaterHeater extends MatterbridgeEndpoint {
22
68
  .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.WaterHeating, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
23
69
  .createDefaultDeviceEnergyManagementModeClusterServer();
24
70
  }
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
+ */
25
90
  createDefaultWaterHeaterManagementClusterServer(heaterTypes, heatDemand, tankPercentage, boostState) {
26
91
  this.behaviors.require(MatterbridgeWaterHeaterManagementServer.with(WaterHeaterManagement.Feature.TankPercent), {
27
- heaterTypes: heaterTypes ?? { immersionElement1: true },
92
+ heaterTypes: heaterTypes ?? { immersionElement1: true }, // Fixed attribute
28
93
  heatDemand: heatDemand ?? {},
29
94
  tankPercentage: tankPercentage ?? 100,
30
95
  boostState: boostState ?? WaterHeaterManagement.BoostState.Inactive,
31
96
  });
32
97
  return this;
33
98
  }
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
+ */
34
107
  createDefaultWaterHeaterModeClusterServer(currentMode, supportedModes) {
35
108
  this.behaviors.require(MatterbridgeWaterHeaterModeServer, {
36
109
  supportedModes: supportedModes ?? [
@@ -47,7 +120,7 @@ export class WaterHeater extends MatterbridgeEndpoint {
47
120
  { label: 'Off', mode: 11, modeTags: [{ value: WaterHeaterMode.ModeTag.Off }] },
48
121
  { label: 'Manual', mode: 12, modeTags: [{ value: WaterHeaterMode.ModeTag.Manual }] },
49
122
  { label: 'Timed', mode: 13, modeTags: [{ value: WaterHeaterMode.ModeTag.Timed }] },
50
- ],
123
+ ], // Fixed attribute
51
124
  currentMode: currentMode ?? 1,
52
125
  });
53
126
  return this;
@@ -60,6 +133,9 @@ export class MatterbridgeWaterHeaterManagementServer extends WaterHeaterManageme
60
133
  device.commandHandler.executeHandler('boost', { request, cluster: WaterHeaterManagementServer.id, attributes: this.state, endpoint: this.endpoint });
61
134
  device.log.debug(`MatterbridgeWaterHeaterManagementServer boost called with: ${JSON.stringify(request)}`);
62
135
  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
63
139
  }
64
140
  cancelBoost() {
65
141
  const device = this.endpoint.stateOf(MatterbridgeServer);
@@ -67,6 +143,9 @@ export class MatterbridgeWaterHeaterManagementServer extends WaterHeaterManageme
67
143
  device.commandHandler.executeHandler('cancelBoost', { request: {}, cluster: WaterHeaterManagementServer.id, attributes: this.state, endpoint: this.endpoint });
68
144
  device.log.debug(`MatterbridgeWaterHeaterManagementServer cancelBoost called`);
69
145
  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
70
149
  }
71
150
  }
72
151
  export class MatterbridgeWaterHeaterModeServer extends WaterHeaterModeServer {
@@ -84,3 +163,4 @@ export class MatterbridgeWaterHeaterModeServer extends WaterHeaterModeServer {
84
163
  return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Success' };
85
164
  }
86
165
  }
166
+ //# sourceMappingURL=waterHeater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waterHeater.js","sourceRoot":"","sources":["../../src/devices/waterHeater.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
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
+ import dgram from 'node:dgram';
24
+ import EventEmitter from 'node:events';
25
+ import { AddressInfo } from 'node:net';
26
+ import { AnsiLogger } from 'node-ansi-logger';
27
+ /**
28
+ * Represents the Dgram events.
29
+ */
30
+ interface DgramEvents {
31
+ error: [error: Error];
32
+ close: [];
33
+ connect: [];
34
+ message: [msg: Buffer, rinfo: dgram.RemoteInfo];
35
+ listening: [address: AddressInfo];
36
+ sent: [msg: Buffer, serverAddress: string, serverPort: number];
37
+ ready: [address: AddressInfo];
38
+ bound: [address: AddressInfo];
39
+ }
40
+ /**
41
+ * This class implements a dgram socket.
42
+ */
43
+ export declare class Dgram extends EventEmitter<DgramEvents> {
44
+ log: AnsiLogger;
45
+ socket: dgram.Socket;
46
+ bound: boolean;
47
+ socketType: 'udp4' | 'udp6';
48
+ interfaceName?: string;
49
+ interfaceAddress?: string;
50
+ interfaceNetmask?: string;
51
+ /**
52
+ * Creates an instance of Dgram.
53
+ *
54
+ * @param {string} name - The name of the socket.
55
+ * @param {'udp4' | 'udp6'} socketType - The type of the socket (IPv4 or IPv6).
56
+ * @param {boolean | undefined} reuseAddr - Whether to allow address reuse.
57
+ * @param {string} [interfaceName] - The name of the network interface to bind to.
58
+ * @param {string} [interfaceAddress] - The address of the network interface to bind to.
59
+ */
60
+ constructor(name: string, socketType: 'udp4' | 'udp6', reuseAddr?: boolean | undefined, interfaceName?: string, interfaceAddress?: string);
61
+ /**
62
+ * Sends a message to the specified server.
63
+ *
64
+ * @param {Buffer} msg - The message buffer to send.
65
+ * @param {string} serverAddress - The IPv4 address of the destination server.
66
+ * @param {number} serverPort - The port of the destination server.
67
+ */
68
+ send(msg: Buffer, serverAddress: string, serverPort: number): void;
69
+ onError(error: Error): void;
70
+ onClose(): void;
71
+ onConnect(): void;
72
+ onSent(msg: Buffer, serverAddress: string, serverPort: number): void;
73
+ onMessage(msg: Buffer, rinfo: dgram.RemoteInfo): void;
74
+ onListening(address: AddressInfo): void;
75
+ onReady(address: AddressInfo): void;
76
+ /**
77
+ * Retrieves the IPv4 address of the specified network interface or the first external IPv4 interface if no interface is specified.
78
+ * Throws an error if no suitable interface or address is found.
79
+ *
80
+ * @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.
81
+ * @returns {string | undefined} The IPv4 address of the specified network interface or the first external IPv4 interface.
82
+ * @throws Error if no suitable interface or address is found.
83
+ */
84
+ getIpv4InterfaceAddress(networkInterface?: string): string | undefined;
85
+ /**
86
+ * Retrieves the IPv6 address of the specified network interface or the first external IPv6 interface if no interface is specified.
87
+ * Throws an error if no suitable interface or address is found.
88
+ *
89
+ * @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.
90
+ * @returns {string | undefined} The IPv6 address of the specified network interface or the first external IPv6 interface.
91
+ * @throws {Error} If no suitable interface or address is found.
92
+ */
93
+ getIpv6InterfaceAddress(networkInterface?: string): string | undefined;
94
+ /**
95
+ * Retrieves the names of all available network interfaces.
96
+ *
97
+ * @returns {string[]} An array of network interface names.
98
+ */
99
+ getInterfacesNames(): string[];
100
+ /**
101
+ * Retrieves the scope ID for all interfaces address '::'.
102
+ *
103
+ * @returns {string} The scope ID of the first found IPv6 address or an empty string.
104
+ */
105
+ getIpv6ScopeIdForAllInterfacesAddress(): string;
106
+ /**
107
+ * Retrieves the interface name from the scope id of an IPv6 address.
108
+ *
109
+ * @param {number} scopeId - The scope id of the IPv6 address.
110
+ * @returns {string | undefined} The interface name or undefined if not found.
111
+ */
112
+ getInterfaceNameFromScopeId(scopeId: number): string | undefined;
113
+ /**
114
+ * Retrieves the netmask of the specified interface address.
115
+ *
116
+ * @param {string} interfaceAddress - The interface address for which to retrieve the netmask.
117
+ * @returns {string | undefined} The netmask of the specified interface address or undefined if not found.
118
+ */
119
+ getNetmask(interfaceAddress: string): string | undefined;
120
+ /**
121
+ * Computes the broadcast address given an IPv4 address and netmask.
122
+ *
123
+ * @param {string | undefined} [ipAddress] - The IPv4 address e.g. "192.168.1.20"
124
+ * @param {string | undefined} [netmask] - The IPv4 netmask e.g. "255.255.255.0"
125
+ * @returns {string | undefined} The computed broadcast address, e.g. "192.168.1.255"
126
+ */
127
+ getIpv4BroadcastAddress(ipAddress: string | undefined, netmask: string | undefined): string | undefined;
128
+ /**
129
+ * Returns the broadcast IPv6 address.
130
+ *
131
+ * @returns {string} The broadcast IPv6 address, e.g. "ff02::1"
132
+ */
133
+ getIpv6BroadcastAddress(): string;
134
+ /**
135
+ * Logs all available network interfaces and their details.
136
+ */
137
+ listNetworkInterfaces(): void;
138
+ }
139
+ export {};
140
+ //# sourceMappingURL=dgram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dgram.d.ts","sourceRoot":"","sources":["../../src/dgram/dgram.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,YAAY,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAIvC,OAAO,EAAE,UAAU,EAAoD,MAAM,kBAAkB,CAAC;AAEhG;;GAEG;AACH,UAAU,WAAW;IACnB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtB,KAAK,EAAE,EAAE,CAAC;IACV,OAAO,EAAE,EAAE,CAAC;IACZ,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAChD,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/D,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC9B,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,qBAAa,KAAM,SAAQ,YAAY,CAAC,WAAW,CAAC;IAClD,GAAG,aAAC;IACJ,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;IACrB,KAAK,UAAS;IACd,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;OAQG;gBACS,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,GAAE,OAAO,GAAG,SAAgB,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM;IA0C/I;;;;;;OAMG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAc3D,OAAO,CAAC,KAAK,EAAE,KAAK;IAIpB,OAAO;IAIP,SAAS;IAIT,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAI7D,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU;IAI9C,WAAW,CAAC,OAAO,EAAE,WAAW;IAKhC,OAAO,CAAC,OAAO,EAAE,WAAW;IAK5B;;;;;;;OAOG;IACH,uBAAuB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAwCtE;;;;;;;OAOG;IACH,uBAAuB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IA0DtE;;;;OAIG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAW9B;;;;OAIG;IACH,qCAAqC,IAAI,MAAM;IAc/C;;;;;OAKG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAchE;;;;;OAKG;IACH,UAAU,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAkBxD;;;;;;OAMG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS;IAUvG;;;;OAIG;IACH,uBAAuB,IAAI,MAAM;IAIjC;;OAEG;IACH,qBAAqB;CAYtB"}
@@ -0,0 +1,348 @@
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
+ import dgram from 'node:dgram';
25
+ import EventEmitter from 'node:events';
26
+ import os from 'node:os';
27
+ // AnsiLogger imports
28
+ import { AnsiLogger, BLUE, db, idn, nf, rs } from 'node-ansi-logger';
29
+ /**
30
+ * This class implements a dgram socket.
31
+ */
32
+ export class Dgram extends EventEmitter {
33
+ log;
34
+ socket;
35
+ bound = false;
36
+ socketType;
37
+ interfaceName;
38
+ interfaceAddress;
39
+ 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
+ constructor(name, socketType, reuseAddr = true, interfaceName, interfaceAddress) {
50
+ super();
51
+ this.log = new AnsiLogger({ logName: name, logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
52
+ this.socket = dgram.createSocket({ type: socketType, reuseAddr });
53
+ this.socketType = socketType;
54
+ this.interfaceName = interfaceName;
55
+ this.interfaceAddress = interfaceAddress;
56
+ this.socket.on('error', (error) => {
57
+ this.log.debug(`Socket error: ${error instanceof Error ? error.message : error}`);
58
+ this.emit('error', error);
59
+ this.onError(error);
60
+ });
61
+ this.socket.on('close', () => {
62
+ this.log.debug('Socket closed');
63
+ this.bound = false;
64
+ this.emit('close');
65
+ this.onClose();
66
+ });
67
+ this.socket.on('connect', () => {
68
+ this.log.info('Socket connected');
69
+ this.emit('connect');
70
+ this.onConnect();
71
+ });
72
+ this.socket.on('message', (msg, rinfo) => {
73
+ this.log.debug(`Socket received a message from ${BLUE}${rinfo.family}${db} ${BLUE}${rinfo.address}${db}:${BLUE}${rinfo.port}${db}`);
74
+ this.emit('message', msg, rinfo);
75
+ this.onMessage(msg, rinfo);
76
+ });
77
+ this.socket.on('listening', () => {
78
+ this.bound = true;
79
+ const address = this.socket.address();
80
+ this.log.debug(`Socket listening on ${BLUE}${address.family}${db} ${BLUE}${address.address}${db}:${BLUE}${address.port}${db}`);
81
+ this.emit('listening', address);
82
+ this.onListening(address);
83
+ });
84
+ }
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
+ send(msg, serverAddress, serverPort) {
93
+ this.socket.send(msg, 0, msg.length, serverPort, serverAddress, (error) => {
94
+ if (error) {
95
+ this.log.error(`Socket failed to send a message: ${error instanceof Error ? error.message : error}`);
96
+ this.emit('error', error);
97
+ this.onError(error);
98
+ }
99
+ else {
100
+ this.log.debug(`Socket sent a message to ${BLUE}${serverAddress}${db}:${BLUE}${serverPort}${db}`);
101
+ this.emit('sent', msg, serverAddress, serverPort);
102
+ this.onSent(msg, serverAddress, serverPort);
103
+ }
104
+ });
105
+ }
106
+ onError(error) {
107
+ this.log.error(`Socket error: ${error instanceof Error ? error.message : error}`);
108
+ }
109
+ onClose() {
110
+ this.log.info(`Socket closed`);
111
+ }
112
+ onConnect() {
113
+ this.log.info(`Socket connected`);
114
+ }
115
+ onSent(msg, serverAddress, serverPort) {
116
+ this.log.info(`Socket sent a message to ${BLUE}${serverAddress}${db}:${BLUE}${serverPort}${db}`);
117
+ }
118
+ onMessage(msg, rinfo) {
119
+ this.log.info(`Socket received a message from ${BLUE}${rinfo.family}${nf} ${BLUE}${rinfo.address}${nf}:${BLUE}${rinfo.port}${nf}`);
120
+ }
121
+ onListening(address) {
122
+ this.log.info(`Socket listening on ${BLUE}${address.family}${nf} ${BLUE}${address.address}${nf}:${BLUE}${address.port}${nf}`);
123
+ this.onReady(address);
124
+ }
125
+ onReady(address) {
126
+ this.log.info(`Socket ready on ${BLUE}${address.family}${nf} ${BLUE}${address.address}${nf}:${BLUE}${address.port}${nf}`);
127
+ this.emit('ready', address);
128
+ }
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
+ getIpv4InterfaceAddress(networkInterface) {
138
+ // Normalize the interface name: treat an empty string as undefined.
139
+ if (networkInterface === '')
140
+ networkInterface = undefined;
141
+ const interfaces = os.networkInterfaces();
142
+ // If a specific interface is provided but not found, warn and fall back.
143
+ if (networkInterface && !interfaces[networkInterface]) {
144
+ this.log.warn(`Interface "${networkInterface}" not found. Using first external IPv4 interface.`);
145
+ networkInterface = undefined;
146
+ }
147
+ // If no interface was specified or the provided one doesn't exist, find the first external IPv4 interface.
148
+ if (!networkInterface) {
149
+ for (const [interfaceName, interfaceDetails] of Object.entries(interfaces)) {
150
+ if (!interfaceDetails)
151
+ continue;
152
+ // Check if at least one external IPv4 address exists on this interface.
153
+ for (const detail of interfaceDetails) {
154
+ if (detail.family === 'IPv4' && !detail.internal) {
155
+ networkInterface = interfaceName;
156
+ break;
157
+ }
158
+ }
159
+ if (networkInterface)
160
+ break;
161
+ }
162
+ }
163
+ if (!networkInterface) {
164
+ throw new Error(`Didn't find an external IPv4 network interface`);
165
+ }
166
+ // Select the first external IPv4 address from the interface.
167
+ const addresses = interfaces[networkInterface];
168
+ const ipv4Address = addresses?.find((addr) => addr.family === 'IPv4' && !addr.internal);
169
+ if (!ipv4Address) {
170
+ throw new Error(`Interface ${networkInterface} does not have an external IPv4 address`);
171
+ }
172
+ return ipv4Address.address;
173
+ }
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
+ getIpv6InterfaceAddress(networkInterface) {
183
+ // Normalize the interface name: treat an empty string as undefined.
184
+ if (networkInterface === '')
185
+ networkInterface = undefined;
186
+ const interfaces = os.networkInterfaces();
187
+ // If a specific interface is provided, verify it exists. Otherwise, warn and use the first external IPv6 interface.
188
+ if (networkInterface && !interfaces[networkInterface]) {
189
+ this.log.warn(`Interface "${networkInterface}" not found. Using first external IPv6 interface.`);
190
+ networkInterface = undefined;
191
+ }
192
+ // If no network interface was specified, search for the first external IPv6 interface.
193
+ if (!networkInterface) {
194
+ for (const [interfaceName, interfaceDetails] of Object.entries(interfaces)) {
195
+ if (!interfaceDetails)
196
+ continue;
197
+ for (const detail of interfaceDetails) {
198
+ if (detail.family === 'IPv6' && !detail.internal) {
199
+ networkInterface = interfaceName;
200
+ break;
201
+ }
202
+ }
203
+ if (networkInterface)
204
+ break;
205
+ }
206
+ }
207
+ if (!networkInterface) {
208
+ throw new Error(`Didn't find an external IPv6 network interface`);
209
+ }
210
+ const addresses = interfaces[networkInterface];
211
+ // Try to find a link-local address and use scopeid
212
+ const linkLocalAddress = addresses?.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.address.startsWith('fe80'));
213
+ if (linkLocalAddress) {
214
+ this.log.debug('Found IPv6 link-local address');
215
+ return linkLocalAddress.scopeid ? `${linkLocalAddress.address}%${process.platform !== 'win32' ? networkInterface : linkLocalAddress.scopeid}` : linkLocalAddress.address;
216
+ }
217
+ this.log.debug('No IPv6 link-local address found');
218
+ // Try to find a unique local address
219
+ const ulaAddress = addresses?.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.address.startsWith('fd') && addr.netmask === 'ffff:ffff:ffff:ffff::');
220
+ if (ulaAddress) {
221
+ this.log.debug('Found IPv6 Unique Local Addresses (ULA) unicast address');
222
+ return ulaAddress.address;
223
+ }
224
+ this.log.debug('No IPv6 Unique Local Addresses (ULA) unicast address found');
225
+ // Try to find a unique local address
226
+ const uniqueLocalAddress = addresses?.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.address.startsWith('fd'));
227
+ if (uniqueLocalAddress) {
228
+ this.log.debug('Found IPv6 Unique Local Addresses (ULA) address');
229
+ return uniqueLocalAddress.address;
230
+ }
231
+ this.log.debug('No IPv6 Unique Local Addresses (ULA) address found');
232
+ throw new Error(`Interface ${networkInterface} does not have a suitable external IPv6 address`);
233
+ }
234
+ /**
235
+ * Retrieves the names of all available network interfaces.
236
+ *
237
+ * @returns {string[]} An array of network interface names.
238
+ */
239
+ getInterfacesNames() {
240
+ const interfaces = os.networkInterfaces();
241
+ const interfaceNames = [];
242
+ for (const name in interfaces) {
243
+ if (interfaces[name]) {
244
+ interfaceNames.push(name);
245
+ }
246
+ }
247
+ return interfaceNames;
248
+ }
249
+ /**
250
+ * Retrieves the scope ID for all interfaces address '::'.
251
+ *
252
+ * @returns {string} The scope ID of the first found IPv6 address or an empty string.
253
+ */
254
+ getIpv6ScopeIdForAllInterfacesAddress() {
255
+ const interfaces = os.networkInterfaces();
256
+ for (const name in interfaces) {
257
+ const iface = interfaces[name];
258
+ if (iface) {
259
+ const ipv6Address = iface.find((addr) => addr.family === 'IPv6' && !addr.internal && addr.scopeid);
260
+ if (ipv6Address) {
261
+ return process.platform === 'win32' ? '%' + String(ipv6Address.scopeid) : '%' + name; // Use the scope ID for Windows, or the interface name for non-Windows platforms
262
+ }
263
+ }
264
+ }
265
+ return '';
266
+ }
267
+ /**
268
+ * Retrieves the interface name from the scope id of an IPv6 address.
269
+ *
270
+ * @param {number} scopeId - The scope id of the IPv6 address.
271
+ * @returns {string | undefined} The interface name or undefined if not found.
272
+ */
273
+ getInterfaceNameFromScopeId(scopeId) {
274
+ const nets = os.networkInterfaces();
275
+ for (const ifaceName in nets) {
276
+ const addresses = nets[ifaceName] || [];
277
+ for (const addr of addresses) {
278
+ // Check for IPv6 addresses with a matching scope id.
279
+ if (addr.family === 'IPv6' && addr.scopeid === scopeId) {
280
+ return ifaceName;
281
+ }
282
+ }
283
+ }
284
+ return undefined;
285
+ }
286
+ /**
287
+ * Retrieves the netmask of the specified interface address.
288
+ *
289
+ * @param {string} interfaceAddress - The interface address for which to retrieve the netmask.
290
+ * @returns {string | undefined} The netmask of the specified interface address or undefined if not found.
291
+ */
292
+ getNetmask(interfaceAddress) {
293
+ // Remove zone index if present (e.g. for IPv6 "fe80::1%eth0")
294
+ const cleanedAddress = interfaceAddress.includes('%') ? interfaceAddress.split('%')[0] : interfaceAddress;
295
+ // Iterate over all interfaces.
296
+ const nets = os.networkInterfaces();
297
+ for (const ifaceName in nets) {
298
+ const ifaceAddresses = nets[ifaceName];
299
+ if (!ifaceAddresses)
300
+ continue;
301
+ for (const addr of ifaceAddresses) {
302
+ if (addr.address === cleanedAddress) {
303
+ return addr.netmask;
304
+ }
305
+ }
306
+ }
307
+ return undefined;
308
+ }
309
+ /**
310
+ * Computes the broadcast address given an IPv4 address and netmask.
311
+ *
312
+ * @param {string | undefined} [ipAddress] - The IPv4 address e.g. "192.168.1.20"
313
+ * @param {string | undefined} [netmask] - The IPv4 netmask e.g. "255.255.255.0"
314
+ * @returns {string | undefined} The computed broadcast address, e.g. "192.168.1.255"
315
+ */
316
+ getIpv4BroadcastAddress(ipAddress, netmask) {
317
+ if (!ipAddress || !netmask) {
318
+ return undefined;
319
+ }
320
+ const ipParts = ipAddress.split('.').map(Number);
321
+ const maskParts = netmask.split('.').map(Number);
322
+ const broadcastParts = ipParts.map((octet, i) => (octet & maskParts[i]) | (255 - maskParts[i]));
323
+ return broadcastParts.join('.');
324
+ }
325
+ /**
326
+ * Returns the broadcast IPv6 address.
327
+ *
328
+ * @returns {string} The broadcast IPv6 address, e.g. "ff02::1"
329
+ */
330
+ getIpv6BroadcastAddress() {
331
+ return 'ff02::1';
332
+ }
333
+ /**
334
+ * Logs all available network interfaces and their details.
335
+ */
336
+ listNetworkInterfaces() {
337
+ const interfaces = os.networkInterfaces();
338
+ for (const [name, addresses] of Object.entries(interfaces)) {
339
+ if (!addresses)
340
+ continue;
341
+ this.log.debug(`Interface: ${idn}${name}${rs}${db}`);
342
+ for (const address of addresses) {
343
+ this.log.debug(`- address ${BLUE}${address.address}${db} netmask ${BLUE}${address.netmask}${db} ${address.mac ? 'MAC: ' + BLUE + address.mac + db : ''} type: ${BLUE}${address.family}${db} ${BLUE}${address.internal ? 'internal' : 'external'}${db} ${address.scopeid !== undefined ? 'scopeid: ' + BLUE + address.scopeid + db : ''} cidr: ${BLUE}${address.cidr}${db}`);
344
+ }
345
+ }
346
+ }
347
+ }
348
+ //# sourceMappingURL=dgram.js.map