matterbridge 3.4.7-dev-20260104-6b10cee → 3.4.7-dev-20260112-bd9e311

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 (172) hide show
  1. package/CHANGELOG.md +11 -4
  2. package/README.md +5 -1
  3. package/dist/broadcastServer.d.ts +29 -0
  4. package/dist/broadcastServerTypes.d.ts +798 -0
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cliEmitter.d.ts +14 -0
  7. package/dist/cliHistory.d.ts +6 -0
  8. package/dist/clusters/export.d.ts +1 -0
  9. package/dist/deviceManager.d.ts +27 -0
  10. package/dist/devices/airConditioner.d.ts +23 -0
  11. package/dist/devices/batteryStorage.d.ts +5 -0
  12. package/dist/devices/cooktop.d.ts +6 -0
  13. package/dist/devices/dishwasher.d.ts +16 -0
  14. package/dist/devices/evse.d.ts +19 -0
  15. package/dist/devices/export.d.ts +16 -0
  16. package/dist/devices/extractorHood.d.ts +5 -0
  17. package/dist/devices/heatPump.d.ts +4 -0
  18. package/dist/devices/laundryDryer.d.ts +9 -0
  19. package/dist/devices/laundryWasher.d.ts +17 -0
  20. package/dist/devices/microwaveOven.d.ts +92 -0
  21. package/dist/devices/oven.d.ts +23 -0
  22. package/dist/devices/refrigerator.d.ts +18 -0
  23. package/dist/devices/roboticVacuumCleaner.d.ts +29 -0
  24. package/dist/devices/solarPower.d.ts +4 -0
  25. package/dist/devices/speaker.d.ts +8 -0
  26. package/dist/devices/temperatureControl.d.ts +145 -0
  27. package/dist/devices/waterHeater.d.ts +37 -0
  28. package/dist/dgram/coap.d.ts +34 -0
  29. package/dist/dgram/dgram.d.ts +45 -0
  30. package/dist/dgram/dgram.js +5 -2
  31. package/dist/dgram/mb_coap.d.ts +1 -0
  32. package/dist/dgram/mb_coap.js +1 -2
  33. package/dist/dgram/mb_mdns.d.ts +1 -0
  34. package/dist/dgram/mb_mdns.js +39 -50
  35. package/dist/dgram/mdns.d.ts +188 -0
  36. package/dist/dgram/multicast.d.ts +18 -0
  37. package/dist/dgram/unicast.d.ts +11 -0
  38. package/dist/frontend.d.ts +58 -0
  39. package/dist/frontendTypes.d.ts +472 -0
  40. package/dist/helpers.d.ts +5 -0
  41. package/dist/index.d.ts +11 -0
  42. package/dist/jestutils/export.d.ts +1 -0
  43. package/dist/jestutils/jestHelpers.d.ts +90 -0
  44. package/dist/logger/export.d.ts +1 -0
  45. package/dist/matter/behaviors.d.ts +1 -0
  46. package/dist/matter/clusters.d.ts +1 -0
  47. package/dist/matter/devices.d.ts +1 -0
  48. package/dist/matter/endpoints.d.ts +1 -0
  49. package/dist/matter/export.d.ts +4 -0
  50. package/dist/matter/types.d.ts +2 -0
  51. package/dist/matterNode.d.ts +84 -0
  52. package/dist/matterbridge.d.ts +152 -0
  53. package/dist/matterbridgeAccessoryPlatform.d.ts +5 -0
  54. package/dist/matterbridgeBehaviors.d.ts +2380 -0
  55. package/dist/matterbridgeDeviceTypes.d.ts +95 -0
  56. package/dist/matterbridgeDynamicPlatform.d.ts +5 -0
  57. package/dist/matterbridgeEndpoint.d.ts +175 -0
  58. package/dist/matterbridgeEndpointHelpers.d.ts +362 -0
  59. package/dist/matterbridgeEndpointTypes.d.ts +96 -0
  60. package/dist/matterbridgePlatform.d.ts +114 -0
  61. package/dist/matterbridgeTypes.d.ts +206 -0
  62. package/dist/pluginManager.d.ts +67 -0
  63. package/dist/shelly.d.ts +24 -0
  64. package/dist/storage/export.d.ts +1 -0
  65. package/dist/update.d.ts +9 -0
  66. package/dist/utils/colorUtils.d.ts +24 -0
  67. package/dist/utils/commandLine.d.ts +6 -0
  68. package/dist/utils/copyDirectory.d.ts +2 -0
  69. package/dist/utils/createDirectory.d.ts +2 -0
  70. package/dist/utils/createZip.d.ts +1 -0
  71. package/dist/utils/deepCopy.d.ts +1 -0
  72. package/dist/utils/deepEqual.d.ts +1 -0
  73. package/dist/utils/error.d.ts +3 -0
  74. package/dist/utils/export.d.ts +12 -0
  75. package/dist/utils/format.d.ts +4 -0
  76. package/dist/utils/hex.d.ts +4 -0
  77. package/dist/utils/inspector.d.ts +24 -0
  78. package/dist/utils/isValid.d.ts +10 -0
  79. package/dist/utils/network.d.ts +25 -0
  80. package/dist/utils/spawn.d.ts +1 -0
  81. package/dist/utils/tracker.d.ts +52 -0
  82. package/dist/utils/wait.d.ts +3 -0
  83. package/dist/workerGlobalPrefix.d.ts +1 -0
  84. package/dist/workerTypes.d.ts +27 -0
  85. package/dist/workers.d.ts +8 -0
  86. package/npm-shrinkwrap.json +1109 -330
  87. package/package.json +9 -2
  88. package/packages/dgram/dist/coap.d.ts +34 -0
  89. package/packages/dgram/dist/coap.js +252 -0
  90. package/packages/dgram/dist/dgram.d.ts +45 -0
  91. package/packages/dgram/dist/dgram.js +255 -0
  92. package/packages/dgram/dist/export.d.ts +5 -0
  93. package/packages/dgram/dist/export.js +5 -0
  94. package/packages/dgram/dist/mdns.d.ts +188 -0
  95. package/packages/dgram/dist/mdns.js +702 -0
  96. package/packages/dgram/dist/multicast.d.ts +18 -0
  97. package/packages/dgram/dist/multicast.js +119 -0
  98. package/packages/dgram/dist/unicast.d.ts +11 -0
  99. package/packages/dgram/dist/unicast.js +40 -0
  100. package/packages/dgram/package.json +110 -0
  101. package/packages/jest-utils/LICENSE +202 -0
  102. package/packages/jest-utils/bmc-button.svg +22 -0
  103. package/packages/jest-utils/dist/export.d.ts +1 -0
  104. package/packages/jest-utils/dist/export.js +1 -0
  105. package/packages/jest-utils/matterbridge.svg +50 -0
  106. package/packages/{mb-lib-test → jest-utils}/package.json +18 -15
  107. package/packages/utils/LICENSE +202 -0
  108. package/packages/utils/bmc-button.svg +22 -0
  109. package/packages/utils/dist/colorUtils.d.ts +24 -0
  110. package/packages/utils/dist/colorUtils.js +187 -0
  111. package/packages/utils/dist/commandLine.d.ts +6 -0
  112. package/packages/utils/dist/commandLine.js +63 -0
  113. package/packages/utils/dist/copyDirectory.d.ts +2 -0
  114. package/packages/utils/dist/copyDirectory.js +39 -0
  115. package/packages/utils/dist/createDirectory.d.ts +2 -0
  116. package/packages/utils/dist/createDirectory.js +21 -0
  117. package/packages/utils/dist/createZip.d.ts +1 -0
  118. package/packages/utils/dist/createZip.js +69 -0
  119. package/packages/utils/dist/deepCopy.d.ts +1 -0
  120. package/packages/utils/dist/deepCopy.js +40 -0
  121. package/packages/utils/dist/deepEqual.d.ts +1 -0
  122. package/packages/utils/dist/deepEqual.js +58 -0
  123. package/packages/utils/dist/error.d.ts +3 -0
  124. package/packages/utils/dist/error.js +12 -0
  125. package/packages/utils/dist/export.d.ts +15 -0
  126. package/packages/utils/dist/export.js +15 -0
  127. package/packages/utils/dist/format.d.ts +4 -0
  128. package/packages/utils/dist/format.js +29 -0
  129. package/packages/utils/dist/githubVersion.d.ts +11 -0
  130. package/packages/utils/dist/githubVersion.js +37 -0
  131. package/packages/utils/dist/hex.d.ts +4 -0
  132. package/packages/utils/dist/hex.js +118 -0
  133. package/packages/utils/dist/inspector.d.ts +24 -0
  134. package/packages/utils/dist/inspector.js +200 -0
  135. package/packages/utils/dist/isValid.d.ts +10 -0
  136. package/packages/utils/dist/isValid.js +69 -0
  137. package/packages/utils/dist/network.d.ts +12 -0
  138. package/packages/utils/dist/network.js +105 -0
  139. package/packages/utils/dist/npmRoot.d.ts +1 -0
  140. package/packages/utils/dist/npmRoot.js +13 -0
  141. package/packages/utils/dist/npmVersion.d.ts +1 -0
  142. package/packages/utils/dist/npmVersion.js +43 -0
  143. package/packages/utils/dist/tracker.d.ts +52 -0
  144. package/packages/utils/dist/tracker.js +201 -0
  145. package/packages/utils/dist/wait.d.ts +3 -0
  146. package/packages/utils/dist/wait.js +73 -0
  147. package/packages/utils/matterbridge.svg +50 -0
  148. package/packages/utils/package.json +110 -0
  149. package/packages/vitest-utils/LICENSE +202 -0
  150. package/packages/vitest-utils/bmc-button.svg +22 -0
  151. package/packages/vitest-utils/dist/export.d.ts +1 -0
  152. package/packages/vitest-utils/dist/export.js +1 -0
  153. package/packages/vitest-utils/matterbridge.svg +50 -0
  154. package/packages/vitest-utils/package.json +109 -0
  155. package/dist/dgram/mdnsReflectorClient.js +0 -176
  156. package/dist/dgram/mdnsReflectorServer.js +0 -301
  157. package/dist/dgram/mdnsReflectorTypes.js +0 -5
  158. package/packages/mb-lib-test/dist/module.d.ts +0 -2
  159. package/packages/mb-lib-test/dist/module.js +0 -2
  160. package/reflector/DockerDesktopSetup.png +0 -0
  161. package/reflector/Reflector.md +0 -158
  162. package/reflector/ReflectorClient.png +0 -0
  163. package/reflector/ReflectorServer.png +0 -0
  164. package/reflector/docker-compose.yml +0 -32
  165. package/reflector/mDnsPacket.png +0 -0
  166. /package/packages/{mb-lib-test → dgram}/LICENSE +0 -0
  167. /package/packages/{mb-lib-test → dgram}/bmc-button.svg +0 -0
  168. /package/packages/{mb-lib-test → dgram}/matterbridge.svg +0 -0
  169. /package/packages/{mb-lib-test/dist/jestutils → jest-utils/dist}/jestHelpers.d.ts +0 -0
  170. /package/packages/{mb-lib-test/dist/jestutils → jest-utils/dist}/jestHelpers.js +0 -0
  171. /package/packages/{mb-lib-test/dist/vitestutils → vitest-utils/dist}/vitestHelpers.d.ts +0 -0
  172. /package/packages/{mb-lib-test/dist/vitestutils → vitest-utils/dist}/vitestHelpers.js +0 -0
@@ -1,301 +0,0 @@
1
- import os from 'node:os';
2
- import { AnsiLogger, BLUE, nt, nf } from 'node-ansi-logger';
3
- import { hasParameter, getStringArrayParameter } from '../utils/commandLine.js';
4
- import { isMdns, isMdnsQuery, isMdnsResponse, Mdns } from './mdns.js';
5
- import { MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS, MDNS_MULTICAST_PORT } from './multicast.js';
6
- import { Unicast } from './unicast.js';
7
- import { MDNS_REFLECTOR_BIND_ADDRESS_IPV4, MDNS_REFLECTOR_BIND_ADDRESS_IPV6, MDNS_REFLECTOR_PORT } from './mdnsReflectorTypes.js';
8
- export class MdnsReflectorServer {
9
- verbose = hasParameter('v') || hasParameter('verbose');
10
- debug = hasParameter('d') || hasParameter('debug') || hasParameter('v') || hasParameter('verbose');
11
- silent = hasParameter('s') || hasParameter('silent');
12
- log = new AnsiLogger({ logName: 'MdnsReflectorServer', logTimestampFormat: 4, logLevel: this.debug ? "debug" : this.silent ? "notice" : "info" });
13
- mdnsIpv4 = new Mdns('mDNS udp4 Server', MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_PORT, 'udp4', true, undefined, MDNS_REFLECTOR_BIND_ADDRESS_IPV4);
14
- mdnsIpv6 = new Mdns('mDNS udp6 Server', MDNS_MULTICAST_IPV6_ADDRESS, MDNS_MULTICAST_PORT, 'udp6', true, undefined, MDNS_REFLECTOR_BIND_ADDRESS_IPV6);
15
- unicastIpv4 = new Unicast('mDNS udp4 Reflector Server', 'udp4', true, undefined, MDNS_REFLECTOR_BIND_ADDRESS_IPV4, MDNS_REFLECTOR_PORT);
16
- unicastIpv6 = new Unicast('mDNS udp6 Reflector Server', 'udp6', true, undefined, MDNS_REFLECTOR_BIND_ADDRESS_IPV6, MDNS_REFLECTOR_PORT);
17
- ipv4Clients = new Map();
18
- ipv6Clients = new Map();
19
- constructor() {
20
- this.log.logNameColor = '\x1b[38;5;115m';
21
- this.mdnsIpv4.log.logNameColor = '\x1b[38;5;115m';
22
- if (!this.debug && !this.verbose && !this.silent)
23
- this.mdnsIpv4.log.logLevel = "warn";
24
- this.mdnsIpv6.log.logNameColor = '\x1b[38;5;115m';
25
- if (!this.debug && !this.verbose && !this.silent)
26
- this.mdnsIpv6.log.logLevel = "warn";
27
- this.unicastIpv4.log.logNameColor = '\x1b[38;5;115m';
28
- if (!this.debug && !this.verbose && !this.silent)
29
- this.unicastIpv4.log.logLevel = "warn";
30
- this.unicastIpv6.log.logNameColor = '\x1b[38;5;115m';
31
- if (!this.debug && !this.verbose && !this.silent)
32
- this.unicastIpv6.log.logLevel = "warn";
33
- const filters = getStringArrayParameter('filter');
34
- if (filters)
35
- this.mdnsIpv4.filters.push(...filters);
36
- if (filters)
37
- this.mdnsIpv6.filters.push(...filters);
38
- }
39
- getBroadcastAddress(mdns) {
40
- try {
41
- const address = mdns.socketType === 'udp4' ? mdns.getIpv4InterfaceAddress(mdns.interfaceName) : mdns.getIpv6InterfaceAddress(mdns.interfaceName);
42
- const mask = mdns.socketType === 'udp4' ? mdns.getNetmask(address) : undefined;
43
- const broadcastAddress = mdns.socketType === 'udp4' ? mdns.getIpv4BroadcastAddress(address, mask) : mdns.getIpv6BroadcastAddress();
44
- return broadcastAddress;
45
- }
46
- catch (error) {
47
- mdns.log.error(`Error getting broadcast address: ${error.message}`);
48
- }
49
- }
50
- upgradeAddress(msg) {
51
- if (!msg || msg.length < 12)
52
- return msg;
53
- const preferredInterfaceName = this.mdnsIpv4.interfaceName ?? this.mdnsIpv6.interfaceName;
54
- const interfaces = os.networkInterfaces();
55
- const pickInterface = () => {
56
- if (preferredInterfaceName) {
57
- const preferred = interfaces[preferredInterfaceName];
58
- if (preferred?.some((info) => info && !info.internal))
59
- return preferredInterfaceName;
60
- }
61
- for (const [name, infos] of Object.entries(interfaces)) {
62
- if (infos?.some((info) => info && !info.internal))
63
- return name;
64
- }
65
- return undefined;
66
- };
67
- const selectedInterfaceName = pickInterface();
68
- this.log.debug(`UpgradeAddress selected interface for address upgrade: ${selectedInterfaceName || 'N/A'}`);
69
- const selectedInfos = selectedInterfaceName ? (interfaces[selectedInterfaceName] ?? []) : [];
70
- const hostIpv4 = selectedInfos.find((info) => info && !info.internal && info.family === 'IPv4')?.address;
71
- const hostIpv6List = (() => {
72
- const set = new Set();
73
- for (const info of selectedInfos) {
74
- if (!info || info.internal || info.family !== 'IPv6')
75
- continue;
76
- const normalized = info.address.split('%')[0].toLowerCase();
77
- if (normalized)
78
- set.add(normalized);
79
- }
80
- return [...set];
81
- })();
82
- this.log.debug(`UpgradeAddress Host IPv4 for address upgrade: ${hostIpv4 || 'N/A'}`);
83
- this.log.debug(`UpgradeAddress Host IPv6 for address upgrade: ${hostIpv6List.length > 0 ? hostIpv6List.join(', ') : 'N/A'}`);
84
- if (!hostIpv4 && hostIpv6List.length === 0)
85
- return msg;
86
- const upgradedMsg = Buffer.from(msg);
87
- const qdCount = upgradedMsg.readUInt16BE(4);
88
- const anCount = upgradedMsg.readUInt16BE(6);
89
- const nsCount = upgradedMsg.readUInt16BE(8);
90
- const arCount = upgradedMsg.readUInt16BE(10);
91
- let offset = 12;
92
- try {
93
- for (let i = 0; i < qdCount; i++) {
94
- const qnameResult = this.mdnsIpv4.decodeDnsName(upgradedMsg, offset);
95
- offset = qnameResult.newOffset;
96
- offset += 4;
97
- if (offset > upgradedMsg.length)
98
- return msg;
99
- }
100
- const hostA = hostIpv4 ? this.mdnsIpv4.encodeA(hostIpv4) : undefined;
101
- const hostAAAAs = hostIpv6List.map((ipv6) => this.mdnsIpv6.encodeAAAA(ipv6));
102
- let hostAAAAIndex = 0;
103
- const upgradeResourceRecords = (count) => {
104
- for (let i = 0; i < count; i++) {
105
- const nameResult = this.mdnsIpv4.decodeDnsName(upgradedMsg, offset);
106
- offset = nameResult.newOffset;
107
- if (offset + 10 > upgradedMsg.length)
108
- return;
109
- const type = upgradedMsg.readUInt16BE(offset);
110
- offset += 2;
111
- offset += 2;
112
- offset += 4;
113
- const rdlength = upgradedMsg.readUInt16BE(offset);
114
- offset += 2;
115
- const rdataOffset = offset;
116
- const endOfRdata = rdataOffset + rdlength;
117
- if (endOfRdata > upgradedMsg.length)
118
- return;
119
- if (type === 1 && rdlength === 4 && hostA) {
120
- hostA.copy(upgradedMsg, rdataOffset);
121
- }
122
- else if (type === 28 && rdlength === 16 && hostAAAAs.length > 0) {
123
- const hostAAAA = hostAAAAs[Math.min(hostAAAAIndex, hostAAAAs.length - 1)];
124
- hostAAAA.copy(upgradedMsg, rdataOffset);
125
- hostAAAAIndex++;
126
- }
127
- offset = endOfRdata;
128
- }
129
- };
130
- upgradeResourceRecords(anCount);
131
- upgradeResourceRecords(nsCount);
132
- upgradeResourceRecords(arCount);
133
- }
134
- catch (error) {
135
- this.log.error(`UpgradeAddress failed to parse message: ${error.message}`);
136
- return msg;
137
- }
138
- this.log.debug(`UpgradeAddress message completed. Interface: ${selectedInterfaceName}, Host IPv4: ${hostIpv4 || 'N/A'}, Host IPv6: ${hostIpv6List.length > 0 ? hostIpv6List.join(', ') : 'N/A'}`);
139
- if (hasParameter('log-reflector-messages')) {
140
- try {
141
- let decodedMessage = this.mdnsIpv4.decodeMdnsMessage(msg);
142
- this.mdnsIpv4.logMdnsMessage(decodedMessage, this.log, '**Original mDNS message');
143
- decodedMessage = this.mdnsIpv4.decodeMdnsMessage(upgradedMsg);
144
- this.mdnsIpv4.logMdnsMessage(decodedMessage, this.log, '**Upgraded mDNS message');
145
- }
146
- catch (error) {
147
- this.log.error(`UpgradeAddress failed to decode message: ${error.message}`);
148
- }
149
- }
150
- return upgradedMsg;
151
- }
152
- async start() {
153
- this.log.notice('mDNS Reflector Server starting...');
154
- this.mdnsIpv4.on('error', (err) => {
155
- this.log.error(`mDNS udp4 Server error:\n${err.stack}`);
156
- });
157
- this.mdnsIpv6.on('error', (err) => {
158
- this.log.error(`mDNS udp6 Server error:\n${err.stack}`);
159
- });
160
- this.unicastIpv4.on('error', (err) => {
161
- this.log.error(`mDNS udp4 Reflector Server error:\n${err.stack}`);
162
- });
163
- this.unicastIpv6.on('error', (err) => {
164
- this.log.error(`mDNS udp6 Reflector Server error:\n${err.stack}`);
165
- });
166
- const promises = [];
167
- promises[0] = new Promise((resolve) => {
168
- this.mdnsIpv4.once('bound', () => resolve());
169
- this.mdnsIpv4.start();
170
- });
171
- promises[1] = new Promise((resolve) => {
172
- this.mdnsIpv6.once('bound', () => resolve());
173
- this.mdnsIpv6.start();
174
- });
175
- promises[2] = new Promise((resolve) => {
176
- this.unicastIpv4.once('bound', () => resolve());
177
- this.unicastIpv4.start();
178
- });
179
- promises[3] = new Promise((resolve) => {
180
- this.unicastIpv6.once('bound', () => resolve());
181
- this.unicastIpv6.start();
182
- });
183
- await Promise.all(promises);
184
- this.mdnsIpv4.socket.setMulticastLoopback(false);
185
- this.mdnsIpv6.socket.setMulticastLoopback(false);
186
- this.mdnsIpv4.on('message', (msg, rinfo) => {
187
- if (this.ipv4Clients.size === 0)
188
- return;
189
- this.log.notice(`Sending ${isMdnsQuery(msg) ? 'query' : 'response'} message from mDNS ipv4 multicast ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to ${this.ipv4Clients.size} ipv4 reflector clients`);
190
- for (const client of this.ipv4Clients.values()) {
191
- this.unicastIpv4.send(msg, client.address, client.port);
192
- }
193
- });
194
- this.mdnsIpv6.on('message', (msg, rinfo) => {
195
- if (this.ipv6Clients.size === 0)
196
- return;
197
- this.log.notice(`Sending ${isMdnsQuery(msg) ? 'query' : 'response'} message from mDNS ipv6 multicast ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to ${this.ipv6Clients.size} ipv6 reflector clients`);
198
- for (const client of this.ipv6Clients.values()) {
199
- this.unicastIpv6.send(msg, client.address, client.port);
200
- }
201
- });
202
- this.unicastIpv4.on('message', (msg, rinfo) => {
203
- this.ipv4Clients.set(`${rinfo.address}:${rinfo.port}`, rinfo);
204
- if (!isMdns(msg)) {
205
- this.log.info(`Received message from reflector client on ipv4 ${BLUE}${rinfo.address}${nf}:${BLUE}${rinfo.port}${nf}: ${msg.toString()}`);
206
- return;
207
- }
208
- const type = isMdnsQuery(msg) ? 'query' : 'response';
209
- this.log.notice(`Reflecting ${type} message from reflector client on ipv4 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to mDNS ipv4 multicast`);
210
- const upgradedMsg = isMdnsResponse(msg) ? this.upgradeAddress(msg) : msg;
211
- this.mdnsIpv4.send(upgradedMsg, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_PORT);
212
- if (hasParameter('broadcast')) {
213
- const broadcastAddress = this.getBroadcastAddress(this.mdnsIpv4);
214
- if (broadcastAddress) {
215
- this.log.notice(`Reflecting ${type} message from reflector client on ipv4 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to ipv4 broadcast address ${BLUE}${broadcastAddress}${nt}:${BLUE}${MDNS_MULTICAST_PORT}${nt}`);
216
- this.mdnsIpv4.send(upgradedMsg, broadcastAddress, MDNS_MULTICAST_PORT);
217
- }
218
- }
219
- if (hasParameter('localhost')) {
220
- this.log.notice(`Reflecting ${type} message from reflector client on ipv4 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to ipv4 localhost address ${BLUE}localhost${nt}:${BLUE}${MDNS_MULTICAST_PORT}${nt}`);
221
- this.mdnsIpv4.send(upgradedMsg, 'localhost', MDNS_MULTICAST_PORT);
222
- }
223
- if (hasParameter('share-with-clients') && this.ipv4Clients.size > 1) {
224
- this.log.notice(`Sharing ${type} message from reflector client on ipv4 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} with other ${this.ipv4Clients.size - 1} ipv4 reflector clients`);
225
- for (const client of this.ipv4Clients.values()) {
226
- if (client.address === rinfo.address && client.port === rinfo.port)
227
- continue;
228
- this.unicastIpv4.send(upgradedMsg, client.address, client.port);
229
- }
230
- }
231
- this.unicastIpv4.send(Buffer.from(`mDNS ipv4 reflector server reflected your ${type} message`), rinfo.address, rinfo.port);
232
- });
233
- this.unicastIpv6.on('message', (msg, rinfo) => {
234
- this.ipv6Clients.set(`${rinfo.address}:${rinfo.port}`, rinfo);
235
- if (!isMdns(msg)) {
236
- this.log.info(`Received message from reflector client on ipv6 ${BLUE}${rinfo.address}${nf}:${BLUE}${rinfo.port}${nf}: ${msg.toString()}`);
237
- return;
238
- }
239
- const type = isMdnsQuery(msg) ? 'query' : 'response';
240
- this.log.notice(`Reflecting ${type} message from reflector client on ipv6 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to mDNS ipv6 multicast`);
241
- const upgradedMsg = isMdnsResponse(msg) ? this.upgradeAddress(msg) : msg;
242
- this.mdnsIpv6.send(upgradedMsg, MDNS_MULTICAST_IPV6_ADDRESS, MDNS_MULTICAST_PORT);
243
- if (hasParameter('broadcast')) {
244
- const broadcastAddress = this.getBroadcastAddress(this.mdnsIpv6);
245
- if (broadcastAddress) {
246
- this.log.notice(`Reflecting ${type} message from reflector client on ipv6 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to ipv6 broadcast address ${BLUE}${broadcastAddress}${nt}:${BLUE}${MDNS_MULTICAST_PORT}${nt}`);
247
- this.mdnsIpv6.send(upgradedMsg, broadcastAddress, MDNS_MULTICAST_PORT);
248
- }
249
- }
250
- if (hasParameter('localhost')) {
251
- this.log.notice(`Reflecting ${type} message from reflector client on ipv6 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} to ipv6 localhost address ${BLUE}localhost${nt}:${BLUE}${MDNS_MULTICAST_PORT}${nt}`);
252
- this.mdnsIpv6.send(upgradedMsg, 'localhost', MDNS_MULTICAST_PORT);
253
- }
254
- if (hasParameter('share-with-clients') && this.ipv6Clients.size > 1) {
255
- this.log.notice(`Sharing ${type} message from reflector client on ipv6 ${BLUE}${rinfo.address}${nt}:${BLUE}${rinfo.port}${nt} with other ${this.ipv6Clients.size - 1} ipv6 reflector clients`);
256
- for (const client of this.ipv6Clients.values()) {
257
- if (client.address === rinfo.address && client.port === rinfo.port)
258
- continue;
259
- this.unicastIpv6.send(upgradedMsg, client.address, client.port);
260
- }
261
- }
262
- this.unicastIpv6.send(Buffer.from(`mDNS ipv6 reflector server reflected your ${type} message`), rinfo.address, rinfo.port);
263
- });
264
- this.log.notice('mDNS Reflector Server started.');
265
- }
266
- async stop() {
267
- this.log.notice('mDNS Reflector Server stopping...');
268
- for (const client of this.ipv4Clients.values()) {
269
- this.log.debug(`Notifying ipv4 client ${client.address}:${client.port} about server stopping`);
270
- this.unicastIpv4.send(Buffer.from('mDNS Reflector Server is stopping'), client.address, client.port);
271
- }
272
- for (const client of this.ipv6Clients.values()) {
273
- this.log.debug(`Notifying ipv6 client ${client.address}:${client.port} about server stopping`);
274
- this.unicastIpv6.send(Buffer.from('mDNS Reflector Server is stopping'), client.address, client.port);
275
- }
276
- await new Promise((resolve) => setTimeout(resolve, 100));
277
- const promises = [];
278
- promises[0] = new Promise((resolve) => {
279
- this.mdnsIpv4.once('close', () => resolve());
280
- this.mdnsIpv4.stop();
281
- });
282
- promises[1] = new Promise((resolve) => {
283
- this.mdnsIpv6.once('close', () => resolve());
284
- this.mdnsIpv6.stop();
285
- });
286
- promises[2] = new Promise((resolve) => {
287
- this.unicastIpv4.once('close', () => resolve());
288
- this.unicastIpv4.stop();
289
- });
290
- promises[3] = new Promise((resolve) => {
291
- this.unicastIpv6.once('close', () => resolve());
292
- this.unicastIpv6.stop();
293
- });
294
- await Promise.all(promises);
295
- this.mdnsIpv4.removeAllListeners();
296
- this.mdnsIpv6.removeAllListeners();
297
- this.unicastIpv4.removeAllListeners();
298
- this.unicastIpv6.removeAllListeners();
299
- this.log.notice('mDNS Reflector Server stopped.');
300
- }
301
- }
@@ -1,5 +0,0 @@
1
- export const MDNS_REFLECTOR_BIND_ADDRESS_IPV4 = '0.0.0.0';
2
- export const MDNS_REFLECTOR_BIND_ADDRESS_IPV6 = '::';
3
- export const MDNS_REFLECTOR_ADDRESS = 'localhost';
4
- export const MDNS_REFLECTOR_HOST_DOCKER = 'host.docker.internal';
5
- export const MDNS_REFLECTOR_PORT = 15353;
@@ -1,2 +0,0 @@
1
- export * as jestHelpers from './jestutils/jestHelpers.js';
2
- export * as vitestHelpers from './vitestutils/vitestHelpers.js';
@@ -1,2 +0,0 @@
1
- export * as jestHelpers from './jestutils/jestHelpers.js';
2
- export * as vitestHelpers from './vitestutils/vitestHelpers.js';
Binary file
@@ -1,158 +0,0 @@
1
- # Matterbridge mDNS reflector
2
-
3
- This project aims to use Matterbridge in these configurations:
4
-
5
- | Docker type | Docker network | OS | Ipv4 | Ipv6 | Share (3) | Home Assistant | Matter Server |
6
- | -------------- | -------------- | ------- | ---- | ---- | --------- | -------------- | ------------- |
7
- | Docker Desktop | bridge (1) | Windows | ✅ | ✅ | ✅ | ✅ | ✅ |
8
- | Docker Desktop | bridge (1) | macOS | ✅ | ✅ | ✅ | ✅ | ✅ |
9
- | Docker Engine | bridge (2) | Linux | ✅ | ✅ | ✅ | ✅ | ✅ |
10
-
11
- (1) - Network host in this configuration is useless cause Docker runs inside a VM.
12
-
13
- (2) - Network host in this configuration works already out of the box cause Docker runs on the host.
14
-
15
- (3) - Share mDNS between separate containers.
16
-
17
- It can also be used to run Home Assistant and Matter Server inside Docker Desktop on Windows and macOS (with network bridge) without using complex VM. You just copy paste this [docker-compose.yml](https://matterbridge.io/reflector/docker-compose.yml).
18
-
19
- Since the mDNS are shared between reflector clients, you can pair Matterbridge running with Docker Desktop to Home Assistant running with Docker Desktop. Even on the same machine.
20
-
21
- <a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/bmc-button.svg" alt="Buy me a coffee" width="120"></a>
22
-
23
- # Prerequisites
24
-
25
- - Docker Desktop
26
-
27
- ## Docker Desktop requirements for Windows and macOS
28
-
29
- See Docker Desktop docs.
30
-
31
- ## Dual Stack IPv4/IPv6 mDNS enabled and No filtering
32
-
33
- ![alt text](DockerDesktopSetup.png)
34
-
35
- # Run Matterbridge in a Docker Desktop container
36
-
37
- We use named volumes for storage, plugins and mattercert.
38
-
39
- We publish the default matterbridge frontend port 8283.
40
-
41
- We publish the matter port range 5550-5559 to allow childbridge mode and server node devices (RVCs).
42
-
43
- macOS
44
-
45
- ```zsh
46
- docker stop matterbridge-test
47
- docker rm matterbridge-test
48
- docker pull luligu/matterbridge:dev
49
- docker run -dit --restart unless-stopped --name matterbridge-test \
50
- -p 8283:8283 -p 5550-5559:5550-5559/udp \
51
- -v storage:/root/.matterbridge -v plugins:/root/Matterbridge -v mattercert:/root/.mattercert \
52
- luligu/matterbridge:dev matterbridge --docker --frontend 8283 --port 5550
53
- docker logs --tail 1000 -f matterbridge-test
54
- ```
55
-
56
- powerShell
57
-
58
- ```powershell
59
- docker stop matterbridge-test
60
- docker rm matterbridge-test
61
- docker pull luligu/matterbridge:dev
62
- docker run -dit --restart unless-stopped --name matterbridge-test `
63
- -p 8283:8283 -p 5550-5559:5550-5559/udp `
64
- -v storage:/root/.matterbridge -v plugins:/root/Matterbridge -v mattercert:/root/.mattercert `
65
- luligu/matterbridge:dev matterbridge --docker --frontend 8283 --port 5550
66
- docker logs --tail 1000 -f matterbridge-test
67
- ```
68
-
69
- You will see that the frontend inside the container is listening on the conainer address
70
-
71
- ```text
72
- [09:02:10.140] [Frontend] The frontend http server is listening on http://172.17.0.2:8283
73
- [09:02:10.140] [Frontend] The frontend http server is listening on http://[fd3d:8954:ffe5::2]:8283
74
- ```
75
-
76
- But since we mapped the port 8283:
77
-
78
- - the frontend is available on the host with localhost:8283, <your_host_ip>:8283 or <your_hostname>:8283.
79
-
80
- - the frontend is available on the lan with <your_host_ip>:8283 or <your_hostname>:8283.
81
-
82
- In the same way the Matter port range 5550-5559 is mapped outside the container to allow the controllers on the lan to discover and connect Matterbridge.
83
-
84
- ## Optional: if you want to see the mDNS inside the Docker Desktop container
85
-
86
- From another terminal run mb_mdns inside the container we created and run before
87
-
88
- ```bash
89
- docker exec -it matterbridge-test mb_mdns --no-timeout
90
- ```
91
-
92
- In a while you will see what mDNS packets are advertised inside the container
93
-
94
- ![alt text](mDnsPacket.png)
95
-
96
- ## Optional: if you want to see ip and routing table inside the Docker Desktop container
97
-
98
- From another terminal run ip a and ip r inside the container we created and run before
99
-
100
- ```bash
101
- docker exec -it matterbridge-test apt-get update
102
- docker exec -it matterbridge-test apt-get install -y --no-install-recommends iproute2 iputils-ping net-tools dnsutils tcpdump netcat-openbsd
103
- docker exec -it matterbridge-test ip a
104
- docker exec -it matterbridge-test ip r
105
- ```
106
-
107
- ### Issues we have there
108
-
109
- 1. The advertised mDNS packets cannot reach the host and the lan cause mDNS are not routed inside Docker Desktop
110
-
111
- 2. The advertised mDNS packets contain wrong A and AAAA records:
112
-
113
- - the advertised address are relative to the container
114
- - those address are not reachable from the host and from the lan
115
-
116
- ## Run the Madderbridge reflector server directly on the host (you need node.js installed on Windows or macOS)
117
-
118
- ```shell
119
- npm install -g matterbridge@dev
120
- mb_mdns --reflector-server --log-reflector-messages --localhost --share-with-clients
121
- ```
122
-
123
- In a while you will see
124
-
125
- ![alt text](ReflectorServer.png)
126
-
127
- ## Run the Madderbridge reflector client in container
128
-
129
- ```shell
130
- docker stop matterbridge-reflector
131
- docker rm matterbridge-reflector
132
- docker pull luligu/reflector-client:latest
133
- docker run -dit --restart unless-stopped --name matterbridge-reflector luligu/reflector-client:latest
134
- docker logs --tail 1000 -f matterbridge-reflector
135
- ```
136
-
137
- In a while you will see
138
-
139
- ![alt text](ReflectorClient.png)
140
-
141
- # Run Home Assistant and Matter Server in Docker compose with Docker Desktop
142
-
143
- ## Prerequisites
144
-
145
- You need the Matterbridge reflector server running on the host from the tutorial above.
146
-
147
- ## Run Home Assitant and Matter Server in Docker Compose with Docker Desktop
148
-
149
- To test the sharing feature (it shares mDNS between all reflector clients),
150
- use this [docker-compose.yml](https://matterbridge.io/reflector/docker-compose.yml).
151
-
152
- With this configuration Home Assistant (with Matter Server) works inside a Docker Desktop container without network host. When asked by Home Assistant, connect to Matter Server with **ws://matterserver:5580/ws**
153
-
154
- ```shell
155
- docker compose down
156
- docker compose pull
157
- docker compose up -d --force-recreate
158
- ```
Binary file
Binary file
@@ -1,32 +0,0 @@
1
- services:
2
- homeassistant:
3
- container_name: homeassistant
4
- image: ghcr.io/home-assistant/home-assistant:stable
5
- restart: unless-stopped
6
- depends_on:
7
- - matterserver
8
- ports:
9
- - "8123:8123"
10
- volumes:
11
- - ./DockerVolumes/homeassistant:/config
12
- environment:
13
- - TZ=Europe/Paris
14
-
15
- matterserver:
16
- container_name: matterserver
17
- image: ghcr.io/home-assistant-libs/python-matter-server:stable
18
- restart: unless-stopped
19
- ports:
20
- - "5580:5580"
21
- - "5540:5540/udp"
22
- volumes:
23
- - ./DockerVolumes/matterserver:/data
24
- environment:
25
- - TZ=Europe/Paris
26
-
27
- reflector:
28
- container_name: reflector
29
- image: luligu/reflector-client:latest
30
- restart: unless-stopped
31
- environment:
32
- - TZ=Europe/Paris
Binary file
File without changes
File without changes