knx.ts 1.0.0
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/LICENSE +21 -0
- package/README.md +211 -0
- package/dist/@types/interfaces/DPTs.d.ts +144 -0
- package/dist/@types/interfaces/DPTs.js +3 -0
- package/dist/@types/interfaces/EMI.d.ts +396 -0
- package/dist/@types/interfaces/EMI.js +2 -0
- package/dist/@types/interfaces/ServiceMessage.d.ts +11 -0
- package/dist/@types/interfaces/ServiceMessage.js +2 -0
- package/dist/@types/interfaces/SystemStatus.d.ts +18 -0
- package/dist/@types/interfaces/SystemStatus.js +2 -0
- package/dist/@types/interfaces/connection.d.ts +139 -0
- package/dist/@types/interfaces/connection.js +2 -0
- package/dist/@types/interfaces/localEndPoint.d.ts +5 -0
- package/dist/@types/interfaces/localEndPoint.js +2 -0
- package/dist/@types/types/AllDpts.d.ts +3 -0
- package/dist/@types/types/AllDpts.js +3 -0
- package/dist/@types/types/DecodedDPTType.d.ts +21 -0
- package/dist/@types/types/DecodedDPTType.js +2 -0
- package/dist/connection/KNXService.d.ts +58 -0
- package/dist/connection/KNXService.js +242 -0
- package/dist/connection/KNXTunneling.d.ts +44 -0
- package/dist/connection/KNXTunneling.js +509 -0
- package/dist/connection/KNXnetIPServer.d.ts +64 -0
- package/dist/connection/KNXnetIPServer.js +900 -0
- package/dist/connection/Router.d.ts +49 -0
- package/dist/connection/Router.js +269 -0
- package/dist/connection/TPUART.d.ts +32 -0
- package/dist/connection/TPUART.js +497 -0
- package/dist/connection/TunnelConnection.d.ts +57 -0
- package/dist/connection/TunnelConnection.js +167 -0
- package/dist/core/CEMI.d.ts +1130 -0
- package/dist/core/CEMI.js +1281 -0
- package/dist/core/ControlField.d.ts +57 -0
- package/dist/core/ControlField.js +120 -0
- package/dist/core/ControlFieldExtended.d.ts +56 -0
- package/dist/core/ControlFieldExtended.js +114 -0
- package/dist/core/EMI.d.ts +2515 -0
- package/dist/core/EMI.js +3898 -0
- package/dist/core/KNXAddInfoTypes.d.ts +225 -0
- package/dist/core/KNXAddInfoTypes.js +602 -0
- package/dist/core/KNXnetIPHeader.d.ts +10 -0
- package/dist/core/KNXnetIPHeader.js +38 -0
- package/dist/core/KNXnetIPStructures.d.ts +179 -0
- package/dist/core/KNXnetIPStructures.js +622 -0
- package/dist/core/MessageCodeField.d.ts +886 -0
- package/dist/core/MessageCodeField.js +399 -0
- package/dist/core/SystemStatus.d.ts +144 -0
- package/dist/core/SystemStatus.js +325 -0
- package/dist/core/data/KNXData.d.ts +7 -0
- package/dist/core/data/KNXData.js +30 -0
- package/dist/core/data/KNXDataDecode.d.ts +396 -0
- package/dist/core/data/KNXDataDecode.js +1186 -0
- package/dist/core/data/KNXDataEncode.d.ts +332 -0
- package/dist/core/data/KNXDataEncode.js +1504 -0
- package/dist/core/enum/APCIEnum.d.ts +587 -0
- package/dist/core/enum/APCIEnum.js +591 -0
- package/dist/core/enum/EnumControlField.d.ts +24 -0
- package/dist/core/enum/EnumControlField.js +36 -0
- package/dist/core/enum/EnumControlFieldExtended.d.ts +36 -0
- package/dist/core/enum/EnumControlFieldExtended.js +41 -0
- package/dist/core/enum/EnumShortACKFrame.d.ts +6 -0
- package/dist/core/enum/EnumShortACKFrame.js +10 -0
- package/dist/core/enum/ErrorCodeSet.d.ts +57 -0
- package/dist/core/enum/ErrorCodeSet.js +2 -0
- package/dist/core/enum/KNXnetIPEnum.d.ts +95 -0
- package/dist/core/enum/KNXnetIPEnum.js +90 -0
- package/dist/core/enum/SAP.d.ts +19 -0
- package/dist/core/enum/SAP.js +23 -0
- package/dist/core/layers/data/APDU.d.ts +38 -0
- package/dist/core/layers/data/APDU.js +115 -0
- package/dist/core/layers/data/NPDU.d.ts +73 -0
- package/dist/core/layers/data/NPDU.js +103 -0
- package/dist/core/layers/data/TPDU.d.ts +53 -0
- package/dist/core/layers/data/TPDU.js +73 -0
- package/dist/core/layers/interfaces/APCI.d.ts +61 -0
- package/dist/core/layers/interfaces/APCI.js +92 -0
- package/dist/core/layers/interfaces/TPCI.d.ts +110 -0
- package/dist/core/layers/interfaces/TPCI.js +196 -0
- package/dist/core/resources/DeviceDescriptorType.d.ts +46 -0
- package/dist/core/resources/DeviceDescriptorType.js +69 -0
- package/dist/errors/DPTNotFound.d.ts +6 -0
- package/dist/errors/DPTNotFound.js +15 -0
- package/dist/errors/InvalidKnxAddresExeption.d.ts +3 -0
- package/dist/errors/InvalidKnxAddresExeption.js +9 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +18 -0
- package/dist/utils/CEMIAdapter.d.ts +16 -0
- package/dist/utils/CEMIAdapter.js +94 -0
- package/dist/utils/KNXHelper.d.ts +78 -0
- package/dist/utils/KNXHelper.js +338 -0
- package/dist/utils/Logger.d.ts +17 -0
- package/dist/utils/Logger.js +96 -0
- package/dist/utils/MessageCodeTranslator.d.ts +19 -0
- package/dist/utils/MessageCodeTranslator.js +77 -0
- package/dist/utils/checksumFrame.d.ts +18 -0
- package/dist/utils/checksumFrame.js +41 -0
- package/dist/utils/localIp.d.ts +7 -0
- package/dist/utils/localIp.js +45 -0
- package/package.json +49 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { KNXService } from "./KNXService";
|
|
3
|
+
import { ExternalManagerOptions } from "../@types/interfaces/connection";
|
|
4
|
+
/**
|
|
5
|
+
* Router: A high-performance, robust Learning Bridge.
|
|
6
|
+
* Architecture strictly follows knxd/src/libserver/router.cpp patterns:
|
|
7
|
+
* 1. Loop Prevention via signature tracking AND Repeat Flag analysis.
|
|
8
|
+
* 2. IA Learning & Selective Routing.
|
|
9
|
+
* 3. Source Address Patching & Sanitization.
|
|
10
|
+
* 4. Client Address Pool Management (KNXnet/IP Tunneling).
|
|
11
|
+
*/
|
|
12
|
+
export declare class Router extends EventEmitter {
|
|
13
|
+
private links;
|
|
14
|
+
private addressTable;
|
|
15
|
+
private recentSignatures;
|
|
16
|
+
private readonly MAX_SIGNATURES_SIZE;
|
|
17
|
+
private routerAddress;
|
|
18
|
+
private clientAddrsStart;
|
|
19
|
+
private clientAddrsCount;
|
|
20
|
+
private clientAddrsUsed;
|
|
21
|
+
private logger;
|
|
22
|
+
constructor(options: ExternalManagerOptions & {
|
|
23
|
+
routerAddress?: string;
|
|
24
|
+
clientAddrs?: string;
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Allocates a free physical address for a tunneling client.
|
|
28
|
+
*/
|
|
29
|
+
getClientAddress(): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Releases an allocated physical address when a client disconnects.
|
|
32
|
+
*/
|
|
33
|
+
releaseClientAddress(addr: string): void;
|
|
34
|
+
private addrToInt;
|
|
35
|
+
private intToAddr;
|
|
36
|
+
registerLink(link: KNXService): void;
|
|
37
|
+
unregisterLink(link: KNXService): void;
|
|
38
|
+
/**
|
|
39
|
+
* Main entry point for any packet received from any link.
|
|
40
|
+
* Based on knxd's Router::recv_L_Data and Router::trigger_cb logic.
|
|
41
|
+
*/
|
|
42
|
+
private processIncoming;
|
|
43
|
+
private learnAddress;
|
|
44
|
+
private route;
|
|
45
|
+
private getSignature;
|
|
46
|
+
private gcSignatures;
|
|
47
|
+
connect(): Promise<void>;
|
|
48
|
+
disconnect(): void;
|
|
49
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Router = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
const TPUART_1 = require("./TPUART");
|
|
6
|
+
const KNXTunneling_1 = require("./KNXTunneling");
|
|
7
|
+
const Logger_1 = require("../utils/Logger");
|
|
8
|
+
/**
|
|
9
|
+
* Router: A high-performance, robust Learning Bridge.
|
|
10
|
+
* Architecture strictly follows knxd/src/libserver/router.cpp patterns:
|
|
11
|
+
* 1. Loop Prevention via signature tracking AND Repeat Flag analysis.
|
|
12
|
+
* 2. IA Learning & Selective Routing.
|
|
13
|
+
* 3. Source Address Patching & Sanitization.
|
|
14
|
+
* 4. Client Address Pool Management (KNXnet/IP Tunneling).
|
|
15
|
+
*/
|
|
16
|
+
class Router extends events_1.EventEmitter {
|
|
17
|
+
links = new Set();
|
|
18
|
+
addressTable = new Map();
|
|
19
|
+
// knxd 'ignore' list: prevents infinite loops across different physical paths
|
|
20
|
+
// Only ignores frames if they are marked as repeated in the KNX Control Field.
|
|
21
|
+
recentSignatures = new Map();
|
|
22
|
+
MAX_SIGNATURES_SIZE = 10000;
|
|
23
|
+
routerAddress = "15.15.0"; // Default, should be configurable
|
|
24
|
+
// Dynamic address pool for clients (like KNXnet/IP Tunneling)
|
|
25
|
+
clientAddrsStart = null;
|
|
26
|
+
clientAddrsCount = 0;
|
|
27
|
+
clientAddrsUsed = [];
|
|
28
|
+
logger;
|
|
29
|
+
constructor(options) {
|
|
30
|
+
super();
|
|
31
|
+
if (options.logOptions) {
|
|
32
|
+
(0, Logger_1.setupLogger)(options.logOptions);
|
|
33
|
+
}
|
|
34
|
+
this.logger = Logger_1.knxLogger.child({ module: "Router" });
|
|
35
|
+
if (options.routerAddress)
|
|
36
|
+
this.routerAddress = options.routerAddress;
|
|
37
|
+
// Parse client addrs e.g. "15.15.10:10"
|
|
38
|
+
if (options.clientAddrs) {
|
|
39
|
+
const parts = options.clientAddrs.split(":");
|
|
40
|
+
if (parts.length === 2) {
|
|
41
|
+
this.clientAddrsStart = parts[0];
|
|
42
|
+
this.clientAddrsCount = parseInt(parts[1], 10);
|
|
43
|
+
this.clientAddrsUsed = new Array(this.clientAddrsCount).fill(false);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (options.tpuart)
|
|
47
|
+
this.registerLink(new TPUART_1.TPUARTConnection(options.tpuart));
|
|
48
|
+
if (options.tunneling)
|
|
49
|
+
options.tunneling.forEach((c) => this.registerLink(new KNXTunneling_1.KNXTunneling(c)));
|
|
50
|
+
this.logger.info(`Router initialized at ${this.routerAddress}`);
|
|
51
|
+
// Periodically clean the signature cache (knxd pattern)
|
|
52
|
+
setInterval(() => this.gcSignatures(), 1000);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Allocates a free physical address for a tunneling client.
|
|
56
|
+
*/
|
|
57
|
+
getClientAddress() {
|
|
58
|
+
if (!this.clientAddrsStart || this.clientAddrsCount === 0)
|
|
59
|
+
return null;
|
|
60
|
+
const startInt = this.addrToInt(this.clientAddrsStart);
|
|
61
|
+
for (let i = 0; i < this.clientAddrsCount; i++) {
|
|
62
|
+
if (!this.clientAddrsUsed[i]) {
|
|
63
|
+
this.clientAddrsUsed[i] = true;
|
|
64
|
+
return this.intToAddr(startInt + i);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null; // Pool exhausted
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Releases an allocated physical address when a client disconnects.
|
|
71
|
+
*/
|
|
72
|
+
releaseClientAddress(addr) {
|
|
73
|
+
if (!this.clientAddrsStart || this.clientAddrsCount === 0)
|
|
74
|
+
return;
|
|
75
|
+
const startInt = this.addrToInt(this.clientAddrsStart);
|
|
76
|
+
const addrInt = this.addrToInt(addr);
|
|
77
|
+
const index = addrInt - startInt;
|
|
78
|
+
if (index >= 0 && index < this.clientAddrsCount) {
|
|
79
|
+
this.clientAddrsUsed[index] = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
addrToInt(addr) {
|
|
83
|
+
const [a, b, c] = addr.split(".").map(Number);
|
|
84
|
+
return ((a & 0x0f) << 12) | ((b & 0x0f) << 8) | (c & 0xff);
|
|
85
|
+
}
|
|
86
|
+
intToAddr(val) {
|
|
87
|
+
return `${(val >> 12) & 0x0f}.${(val >> 8) & 0x0f}.${val & 0xff}`;
|
|
88
|
+
}
|
|
89
|
+
registerLink(link) {
|
|
90
|
+
if (this.links.has(link))
|
|
91
|
+
return;
|
|
92
|
+
this.links.add(link);
|
|
93
|
+
this.logger.info(`Link registered: ${link.constructor.name}`);
|
|
94
|
+
link.on("indication", (cemi) => {
|
|
95
|
+
this.processIncoming(cemi, link);
|
|
96
|
+
});
|
|
97
|
+
link.on("error", (err) => {
|
|
98
|
+
this.logger.error({ link: link.constructor.name, err: err.message }, "Link error");
|
|
99
|
+
this.emit("error", { link, error: err });
|
|
100
|
+
});
|
|
101
|
+
// knxd pattern: cleanup when link goes down
|
|
102
|
+
link.on("disconnected", () => {
|
|
103
|
+
this.logger.info(`Link disconnected: ${link.constructor.name}`);
|
|
104
|
+
this.unregisterLink(link);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
unregisterLink(link) {
|
|
108
|
+
if (!this.links.has(link))
|
|
109
|
+
return;
|
|
110
|
+
// Cleanup routing table
|
|
111
|
+
for (const [addr, l] of this.addressTable.entries()) {
|
|
112
|
+
if (l === link) {
|
|
113
|
+
this.addressTable.delete(addr);
|
|
114
|
+
// If it was a dynamic client address, release it
|
|
115
|
+
this.releaseClientAddress(addr);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.links.delete(link);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Main entry point for any packet received from any link.
|
|
122
|
+
* Based on knxd's Router::recv_L_Data and Router::trigger_cb logic.
|
|
123
|
+
*/
|
|
124
|
+
processIncoming(cemi, source) {
|
|
125
|
+
const cemiAny = cemi;
|
|
126
|
+
let src = cemiAny.sourceAddress;
|
|
127
|
+
// 1. Source Validation (knxd pattern):
|
|
128
|
+
// If we know this IA is on another link, discard to prevent loops/spoofing.
|
|
129
|
+
if (src && src !== "0.0.0") {
|
|
130
|
+
if (src === this.routerAddress) {
|
|
131
|
+
// We shouldn't receive a packet claiming to be us from the outside.
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const existingLink = this.addressTable.get(src);
|
|
135
|
+
if (existingLink && existingLink !== source) {
|
|
136
|
+
return; // Ignore packet from "wrong" interface
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// 2. Source Patching (Standard KNX Requirement)
|
|
140
|
+
// If src is 0.0.0, it must be replaced by the router's/client's address
|
|
141
|
+
if (!src || src === "0.0.0") {
|
|
142
|
+
cemiAny.sourceAddress =
|
|
143
|
+
"individualAddress" in source.options &&
|
|
144
|
+
source.options.individualAddress
|
|
145
|
+
? source.options.individualAddress
|
|
146
|
+
: this.routerAddress;
|
|
147
|
+
src = cemiAny.sourceAddress;
|
|
148
|
+
}
|
|
149
|
+
// 3. IA Learning
|
|
150
|
+
this.learnAddress(src, source);
|
|
151
|
+
// 4. Loop Prevention (knxd strict pattern)
|
|
152
|
+
const buf = cemi.toBuffer();
|
|
153
|
+
// In CEMI, Ctrl1 is at offset `2 + AddIL`
|
|
154
|
+
const addIL = buf[1];
|
|
155
|
+
const ctrl1 = buf[2 + addIL];
|
|
156
|
+
// KNX Standard: Repeat bit is bit 5 (0x20). Active LOW (0 = repeated frame).
|
|
157
|
+
const isRepeated = (ctrl1 & 0x20) === 0;
|
|
158
|
+
const signature = this.getSignature(buf, addIL);
|
|
159
|
+
if (isRepeated) {
|
|
160
|
+
if (this.recentSignatures.has(signature)) {
|
|
161
|
+
this.logger.debug({ signature, src }, "Loop prevented: duplicated repeated frame dropped");
|
|
162
|
+
return; // Drop repeated packet we've recently seen on the bus
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Always record the signature. If a loop occurs, the echoed packet will have
|
|
166
|
+
// the repeat flag set to 0 (since it failed to ACK or was physically echoed),
|
|
167
|
+
// and we will drop it next time.
|
|
168
|
+
if (this.recentSignatures.size >= this.MAX_SIGNATURES_SIZE) {
|
|
169
|
+
const firstKey = this.recentSignatures.keys().next().value;
|
|
170
|
+
if (firstKey !== undefined)
|
|
171
|
+
this.recentSignatures.delete(firstKey);
|
|
172
|
+
}
|
|
173
|
+
this.recentSignatures.set(signature, Date.now());
|
|
174
|
+
// 5. Route
|
|
175
|
+
this.route(cemi, source);
|
|
176
|
+
}
|
|
177
|
+
learnAddress(src, source) {
|
|
178
|
+
// knxd pattern: don't learn 0.0.0 or special 15.15.255 (0xFFFF) addresses
|
|
179
|
+
if (src !== "0.0.0" && src !== "15.15.255") {
|
|
180
|
+
if (this.addressTable.get(src) !== source) {
|
|
181
|
+
this.addressTable.set(src, source);
|
|
182
|
+
this.logger.debug(`Learned IA ${src} on link ${source.constructor.name}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
route(cemi, source) {
|
|
187
|
+
const cemiAny = cemi;
|
|
188
|
+
// Hop Count Management (Protect the whole network)
|
|
189
|
+
if (cemiAny.controlField2 &&
|
|
190
|
+
typeof cemiAny.controlField2.hopCount === "number") {
|
|
191
|
+
const hops = cemiAny.controlField2.hopCount;
|
|
192
|
+
if (hops === 0) {
|
|
193
|
+
this.logger.debug({ src: cemiAny.sourceAddress, dst: cemiAny.destinationAddress }, "Packet dropped: hop count reached 0");
|
|
194
|
+
return; // Drop packet
|
|
195
|
+
}
|
|
196
|
+
if (hops < 7)
|
|
197
|
+
cemiAny.controlField2.hopCount = hops - 1;
|
|
198
|
+
}
|
|
199
|
+
const isGroup = cemiAny.controlField2?.addressType === 1;
|
|
200
|
+
const dest = cemiAny.destinationAddress;
|
|
201
|
+
// If packet is destined for the router itself, consume it and don't route
|
|
202
|
+
if (!isGroup && dest === this.routerAddress) {
|
|
203
|
+
this.logger.debug({ src: cemiAny.sourceAddress }, "Packet consumed by router local address");
|
|
204
|
+
this.emit("indication", cemi);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// Selective Routing (IA)
|
|
208
|
+
if (!isGroup && dest && dest !== "0.0.0" && dest !== "15.15.255") {
|
|
209
|
+
const target = this.addressTable.get(dest);
|
|
210
|
+
if (target) {
|
|
211
|
+
if (target !== source) {
|
|
212
|
+
target.send(cemi).catch((err) => {
|
|
213
|
+
this.logger.debug({ target: target.constructor.name, err: err.message }, "Selective routing failed");
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Send to upper layers (KNXnet/IP server core)
|
|
217
|
+
this.emit("indication", cemi);
|
|
218
|
+
return; // Do not flood
|
|
219
|
+
}
|
|
220
|
+
// If target is unknown, knxd broadcasts it to all interfaces
|
|
221
|
+
}
|
|
222
|
+
// Flood to all links except source, respecting filters (knxd pattern)
|
|
223
|
+
for (const link of this.links) {
|
|
224
|
+
if (link === source)
|
|
225
|
+
continue;
|
|
226
|
+
// Avoid looping back to the physical source address if known via another route
|
|
227
|
+
if (this.addressTable.get(cemiAny.sourceAddress) === link)
|
|
228
|
+
continue;
|
|
229
|
+
// Check if the link should filter this message
|
|
230
|
+
if (isGroup) {
|
|
231
|
+
if (link.shouldFilterGroup && !link.shouldFilterGroup(dest))
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
if (link.shouldFilterIA && !link.shouldFilterIA(dest))
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
link.send(cemi).catch((err) => {
|
|
239
|
+
this.logger.debug({ link: link.constructor.name, err: err.message }, "Flooding routing failed for link");
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// Notify upper layers
|
|
243
|
+
this.emit("indication", cemi);
|
|
244
|
+
}
|
|
245
|
+
getSignature(buf, addIL) {
|
|
246
|
+
// Signature based on Dst + APCI + Data (knxd style)
|
|
247
|
+
// We skip Src and HopCount because they change during routing
|
|
248
|
+
// Payload starts after CEMI header (2) + AddIL + Ctrl1 (1) + Ctrl2 (1) + Src (2)
|
|
249
|
+
// Actually, taking from Dst onwards is a solid signature.
|
|
250
|
+
// Dst is at offset 2 + addIL + 4
|
|
251
|
+
const dstOffset = 2 + addIL + 4;
|
|
252
|
+
return buf.subarray(dstOffset).toString("hex");
|
|
253
|
+
}
|
|
254
|
+
gcSignatures() {
|
|
255
|
+
const now = Date.now();
|
|
256
|
+
for (const [sig, time] of this.recentSignatures) {
|
|
257
|
+
// knxd keeps them for 1 second
|
|
258
|
+
if (now - time > 1000)
|
|
259
|
+
this.recentSignatures.delete(sig);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async connect() {
|
|
263
|
+
await Promise.all(Array.from(this.links).map((l) => l.connect()));
|
|
264
|
+
}
|
|
265
|
+
disconnect() {
|
|
266
|
+
this.links.forEach((l) => l.disconnect());
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
exports.Router = Router;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { KNXService } from "./KNXService";
|
|
2
|
+
import { TPUARTOptions } from "../@types/interfaces/connection";
|
|
3
|
+
import { ServiceMessage } from "../@types/interfaces/ServiceMessage";
|
|
4
|
+
export declare class TPUARTConnection extends KNXService {
|
|
5
|
+
private serialPort;
|
|
6
|
+
private receiver;
|
|
7
|
+
private connectionState;
|
|
8
|
+
private initPromise;
|
|
9
|
+
private msgQueue;
|
|
10
|
+
private isProcessing;
|
|
11
|
+
private lastSentFrame;
|
|
12
|
+
private keepaliveTimer;
|
|
13
|
+
private confirmationTimer;
|
|
14
|
+
private initTimer;
|
|
15
|
+
private initRetryCount;
|
|
16
|
+
private isBusmonitorMode;
|
|
17
|
+
constructor(options: TPUARTOptions);
|
|
18
|
+
private handleFatalError;
|
|
19
|
+
private stopTimers;
|
|
20
|
+
private resetKeepalive;
|
|
21
|
+
connect(): Promise<void>;
|
|
22
|
+
private sendResetRequest;
|
|
23
|
+
disconnect(): Promise<void>;
|
|
24
|
+
setBusmonitor(enabled: boolean): Promise<void>;
|
|
25
|
+
send(data: Buffer | ServiceMessage): Promise<void>;
|
|
26
|
+
private enqueueFrame;
|
|
27
|
+
private processQueue;
|
|
28
|
+
private toUartServices;
|
|
29
|
+
_handleControlByte(byte: number): void;
|
|
30
|
+
private writeRaw;
|
|
31
|
+
private requestState;
|
|
32
|
+
}
|