Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

knxultimate

Package Overview
Dependencies
Maintainers
0
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

knxultimate - npm Package Compare versions

Comparing version 2.3.5 to 3.0.0-beta.0

10

build/KNXClient.d.ts

@@ -65,2 +65,3 @@ /// <reference types="node" />

localSocketAddress?: string;
KNXQueueSendIntervalMilliseconds?: number;
} & KNXLoggerOptions;

@@ -95,2 +96,6 @@ export declare function getDecodedKeyring(): string;

physAddr: KNXAddress;
private limiter;
private commandQueue;
private exitProcessingKNXQueueLoop;
private currentItemHandledByTheQueue;
constructor(options: KNXClientOptions);

@@ -104,3 +109,5 @@ get channelID(): number;

private clearAllTimers;
send(knxPacket: KNXPacket): void;
processKnxPacketQueueItem: (_knxPacket: KNXPacket) => Promise<void>;
handleKNXQueue: () => Promise<void>;
send(_knxPacket: KNXPacket, _ACK: KNXTunnelingRequest, _priority: boolean, _expectedSeqNumberForACK: number): void;
write(dstAddress: KNXAddress | string, data: any, dptid: string | number): void;

@@ -123,2 +130,3 @@ respond(dstAddress: KNXAddress | string, data: Buffer, dptid: string | number): void;

private getSeqNumber;
private getCurrentItemHandledByTheQueue;
private incSeqNumber;

@@ -125,0 +133,0 @@ private setTimerWaitingForACK;

275

build/KNXClient.js

@@ -51,2 +51,3 @@ "use strict";

const utils_1 = require("./utils");
const limiter_1 = require("limiter");
var ConncetionState;

@@ -87,3 +88,3 @@ (function (ConncetionState) {

ipPort: 3671,
hostProtocol: 'TunnelUDP',
hostProtocol: 'Multicast',
isSecureKNXEnabled: false,

@@ -96,2 +97,3 @@ suppress_ack_ldatareq: false,

jKNXSecureKeyring: {},
KNXQueueSendIntervalMilliseconds: 25,
};

@@ -114,4 +116,90 @@ function getDecodedKeyring() {

constructor(options) {
var _a;
super();
this.commandQueue = [];
this.processKnxPacketQueueItem = async (_knxPacket) => {
var _a, _b, _c, _d, _e;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: processKnxPacketQueueItem: Processing queued KNX. commandQueue.length: ${this.commandQueue.length} ${_knxPacket.header.service_type}`);
if (_knxPacket instanceof KNXConnectRequest_1.default) {
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.debug(`Sending KNX packet: ${_knxPacket.constructor.name} Host:${this._peerHost}:${this._peerPort}`);
}
if (_knxPacket instanceof KNXTunnelingRequest_1.default ||
_knxPacket instanceof KNXRoutingIndication_1.default) {
let sTPCI = '';
if (_knxPacket.cEMIMessage.npdu.isGroupRead) {
sTPCI = 'Read';
}
if (_knxPacket.cEMIMessage.npdu.isGroupResponse) {
sTPCI = 'Response';
}
if (_knxPacket.cEMIMessage.npdu.isGroupWrite) {
sTPCI = 'Write';
}
let sDebugString = `Data: ${JSON.stringify(_knxPacket.cEMIMessage.npdu)}`;
sDebugString += ` srcAddress: ${_knxPacket.cEMIMessage.srcAddress.toString()}`;
sDebugString += ` dstAddress: ${_knxPacket.cEMIMessage.dstAddress.toString()}`;
(_c = this.sysLogger) === null || _c === void 0 ? void 0 : _c.debug(`Sending KNX packet: ${_knxPacket.constructor.name} ${sDebugString} Host:${this._peerHost}:${this._peerPort} channelID:${_knxPacket.channelID} seqCounter:${_knxPacket.seqCounter} Dest:${_knxPacket.cEMIMessage.dstAddress.toString()}`, ` Data:${_knxPacket.cEMIMessage.npdu.dataValue.toString('hex')} TPCI:${sTPCI}`);
}
if (this._options.hostProtocol === 'Multicast' ||
this._options.hostProtocol === 'TunnelUDP') {
try {
;
this._clientSocket.send(_knxPacket.toBuffer(), this._peerPort, this._peerHost, (err) => {
var _a;
if (err) {
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`Sending KNX packet: Send UDP sending error: ${err.message}`);
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
(_d = this.sysLogger) === null || _d === void 0 ? void 0 : _d.error(`Sending KNX packet: Send UDP Catch error: ${error.message} ${typeof _knxPacket} seqCounter:${_knxPacket.seqCounter || ''}`);
this.emit(KNXClientEvents.error, error);
}
}
else {
try {
;
this._clientSocket.write(_knxPacket.toBuffer(), (err) => {
var _a;
if (err) {
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`Sending KNX packet: Send TCP sending error: ${err.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
(_e = this.sysLogger) === null || _e === void 0 ? void 0 : _e.error(`Sending KNX packet: Send TCP Catch error: ${error.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, error);
}
}
};
this.handleKNXQueue = async () => {
var _a, _b, _c, _d;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: handleKNXQueue: Start Processing queued KNX.`);
do {
const remainingRequests = await this.limiter.removeTokens(1);
if (this.commandQueue.length > 0 && this._clearToSend) {
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.debug(`\n\nKNXClient: START.`);
const item = this.commandQueue.pop();
this.currentItemHandledByTheQueue = item;
if (item.ACK !== undefined) {
await this.processKnxPacketQueueItem(item.knxPacket);
this.setTimerWaitingForACK(item.ACK);
}
else {
await this.processKnxPacketQueueItem(item.knxPacket);
}
(_c = this.sysLogger) === null || _c === void 0 ? void 0 : _c.debug(`KNXClient: END.`);
}
if (this.exitProcessingKNXQueueLoop)
return;
} while (this.exitProcessingKNXQueueLoop === false);
(_d = this.sysLogger) === null || _d === void 0 ? void 0 : _d.debug(`KNXClient: handleKNXQueue: Stop Processing queued KNX.`);
};
this.timers = new Map();
this.commandQueue = [];
this.exitProcessingKNXQueueLoop = false;
if (options === undefined) {

@@ -141,2 +229,6 @@ options = optionsDefaults;

this.jKNXSecureKeyring = this._options.jKNXSecureKeyring;
this.limiter = new limiter_1.RateLimiter({
tokensPerInterval: 1,
interval: this._options.KNXQueueSendIntervalMilliseconds,
});
this.on('error', (error) => { });

@@ -150,3 +242,3 @@ if (typeof this._options.physAddr === 'string') {

catch (error) {
this.sysLogger.error(`ipAddressHelper.getLocalAddress:${error.message}`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`ipAddressHelper.getLocalAddress:${error.message}`);
throw error;

@@ -160,2 +252,3 @@ }

this._clientSocket.bind({ port: null, address: this._options.localIPAddress }, () => {
var _a;
try {

@@ -169,3 +262,3 @@ ;

catch (error) {
this.sysLogger.error(`UDP: Error setting SetTTL ${error.message}` || '');
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`UDP: Error setting SetTTL ${error.message}` || '');
}

@@ -195,2 +288,3 @@ });

this._clientSocket.bind(this._peerPort, () => {
var _a, _b;
const client = this._clientSocket;

@@ -202,3 +296,3 @@ try {

catch (error) {
this.sysLogger.error(`Multicast: Error setting SetTTL ${error.message}` ||
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`Multicast: Error setting SetTTL ${error.message}` ||
'');

@@ -210,3 +304,3 @@ }

catch (err) {
this.sysLogger.error('Multicast: cannot add membership (%s)', err);
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.error('Multicast: cannot add membership (%s)', err);
this.emit(KNXClientEvents.error, err);

@@ -224,2 +318,3 @@ }

getKNXDataBuffer(data, dptid) {
var _a;
if (typeof dptid === 'number') {

@@ -232,3 +327,3 @@ dptid = dptid.toString();

const isSixBits = adpu.bitlength <= 6;
this.sysLogger.trace(`isSixBits:${isSixBits} Includes (should be = isSixBits):${[
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.trace(`isSixBits:${isSixBits} Includes (should be = isSixBits):${[
1, 2, 3, 5, 9, 10, 11, 14, 18,

@@ -259,6 +354,7 @@ ].includes(iDatapointType)} ADPU BitLength:${adpu.bitlength}`);

setTimer(type, cb, delay) {
var _a;
if (this.timers.has(type)) {
clearTimeout(this.timers.get(type));
this.timers.delete(type);
this.sysLogger.warn(`Timer "${type}" was already running`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.warn(`Timer "${type}" was already running`);
}

@@ -283,56 +379,17 @@ this.timers.set(type, setTimeout(() => {

}
send(knxPacket) {
if (knxPacket instanceof KNXConnectRequest_1.default) {
this.sysLogger.debug(`Sending KNX packet: ${knxPacket.constructor.name} Host:${this._peerHost}:${this._peerPort}`);
send(_knxPacket, _ACK, _priority, _expectedSeqNumberForACK) {
var _a;
const toBeAdded = {
knxPacket: _knxPacket,
ACK: _ACK,
expectedSeqNumberForACK: _expectedSeqNumberForACK,
};
if (_priority) {
this.commandQueue.push(toBeAdded);
this._clearToSend = true;
}
if (knxPacket instanceof KNXTunnelingRequest_1.default ||
knxPacket instanceof KNXRoutingIndication_1.default) {
let sTPCI = '';
if (knxPacket.cEMIMessage.npdu.isGroupRead) {
sTPCI = 'Read';
}
if (knxPacket.cEMIMessage.npdu.isGroupResponse) {
sTPCI = 'Response';
}
if (knxPacket.cEMIMessage.npdu.isGroupWrite) {
sTPCI = 'Write';
}
let sDebugString = `Data: ${JSON.stringify(knxPacket.cEMIMessage.npdu)}`;
sDebugString += ` srcAddress: ${knxPacket.cEMIMessage.srcAddress.toString()}`;
sDebugString += ` dstAddress: ${knxPacket.cEMIMessage.dstAddress.toString()}`;
this.sysLogger.debug(`Sending KNX packet: ${knxPacket.constructor.name} ${sDebugString} Host:${this._peerHost}:${this._peerPort} channelID:${knxPacket.channelID} seqCounter:${knxPacket.seqCounter} Dest:${knxPacket.cEMIMessage.dstAddress.toString()}`, ` Data:${knxPacket.cEMIMessage.npdu.dataValue.toString('hex')} TPCI:${sTPCI}`);
}
if (this._options.hostProtocol === 'Multicast' ||
this._options.hostProtocol === 'TunnelUDP') {
try {
;
this._clientSocket.send(knxPacket.toBuffer(), this._peerPort, this._peerHost, (err) => {
if (err) {
this.sysLogger.error(`Sending KNX packet: Send UDP sending error: ${err.message}`);
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
this.sysLogger.error(`Sending KNX packet: Send UDP Catch error: ${error.message} ${typeof knxPacket} seqCounter:${knxPacket.seqCounter || ''}`);
this.emit(KNXClientEvents.error, error);
}
}
else {
try {
;
this._clientSocket.write(knxPacket.toBuffer(), (err) => {
if (err) {
this.sysLogger.error(`Sending KNX packet: Send TCP sending error: ${err.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
this.sysLogger.error(`Sending KNX packet: Send TCP Catch error: ${error.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, error);
}
this.commandQueue.unshift(toBeAdded);
}
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: ADDED TELEGRAM TO COMMANDQUEUE. Len: ${this.commandQueue.length}`);
}

@@ -354,3 +411,3 @@ write(dstAddress, data, dptid) {

const knxPacketRequest = KNXProtocol_1.default.newKNXRoutingIndication(cEMIMessage);
this.send(knxPacketRequest);
this.send(knxPacketRequest, undefined, false, this.getSeqNumber());
}

@@ -367,4 +424,3 @@ else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest);
this.send(knxPacketRequest);
this.send(knxPacketRequest, knxPacketRequest, false, this.getSeqNumber());
if (this._options.localEchoInTunneling)

@@ -389,3 +445,3 @@ this.emit(KNXClientEvents.indication, knxPacketRequest, true);

const knxPacketRequest = KNXProtocol_1.default.newKNXRoutingIndication(cEMIMessage);
this.send(knxPacketRequest);
this.send(knxPacketRequest, undefined, false, this.getSeqNumber());
}

@@ -402,4 +458,3 @@ else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest);
this.send(knxPacketRequest);
this.send(knxPacketRequest, knxPacketRequest, false, this.getSeqNumber());
if (this._options.localEchoInTunneling)

@@ -423,3 +478,3 @@ this.emit(KNXClientEvents.indication, knxPacketRequest, true);

const knxPacketRequest = KNXProtocol_1.default.newKNXRoutingIndication(cEMIMessage);
this.send(knxPacketRequest);
this.send(knxPacketRequest, undefined, false, this.getSeqNumber());
}

@@ -436,4 +491,3 @@ else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest);
this.send(knxPacketRequest);
this.send(knxPacketRequest, knxPacketRequest, false, this.getSeqNumber());
if (this._options.localEchoInTunneling)

@@ -444,6 +498,7 @@ this.emit(KNXClientEvents.indication, knxPacketRequest, true);

writeRaw(dstAddress, rawDataBuffer, bitlength) {
var _a;
if (this._connectionState !== ConncetionState.CONNECTED)
throw new Error('The socket is not connected. Unable to access the KNX BUS');
if (!Buffer.isBuffer(rawDataBuffer)) {
this.sysLogger.error('KNXClient: writeRaw: Value must be a buffer! ');
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error('KNXClient: writeRaw: Value must be a buffer! ');
return;

@@ -474,3 +529,3 @@ }

const knxPacketRequest = KNXProtocol_1.default.newKNXRoutingIndication(cEMIMessage);
this.send(knxPacketRequest);
this.send(knxPacketRequest, undefined, false, this.getSeqNumber());
}

@@ -489,4 +544,3 @@ else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest);
this.send(knxPacketRequest);
this.send(knxPacketRequest, knxPacketRequest, false, this.getSeqNumber());
if (this._options.localEchoInTunneling)

@@ -551,2 +605,3 @@ this.emit(KNXClientEvents.indication, knxPacketRequest, true);

}
this.handleKNXQueue();
this._connectionState = ConncetionState.CONNECTING;

@@ -585,7 +640,8 @@ this._numFailedTelegramACK = 0;

async closeSocket() {
this.exitProcessingKNXQueueLoop = true;
return new Promise((resolve) => {
var _a;
if (!this._clientSocket)
return;
const cb = () => {
this._clientSocket = null;
resolve();

@@ -604,3 +660,3 @@ };

catch (error) {
this.sysLogger.error(`KNXClient: into async closeSocket(): ${error.stack}`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`KNXClient: into async closeSocket(): ${error.stack}`);
resolve();

@@ -611,2 +667,4 @@ }

async Disconnect() {
var _a;
this.exitProcessingKNXQueueLoop = true;
if (this._clientSocket === null) {

@@ -621,3 +679,3 @@ throw new Error('No client socket defined');

if (this._channelID === null) {
this.sysLogger.debug(`KNXClient: into Disconnect(), channel id is not defined so skip disconnect packet and close socket`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: into Disconnect(), channel id is not defined so skip disconnect packet and close socket`);
await this.closeSocket();

@@ -637,3 +695,4 @@ return;

async setDisconnected(_sReason = '') {
this.sysLogger.debug(`KNXClient: called _setDisconnected ${this._options.ipAddr}:${this._options.ipPort} ${_sReason}`);
var _a;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: called _setDisconnected ${this._options.ipAddr}:${this._options.ipPort} ${_sReason}`);
this._connectionState = ConncetionState.DISCONNECTED;

@@ -656,3 +715,4 @@ this.clearAllTimers();

this.setTimer(KNXTimer.CONNECTION_STATE, () => {
this.sysLogger.error(`KNXClient: getConnectionStatus Timeout ${this._heartbeatFailures} out of ${this.max_HeartbeatFailures}`);
var _a;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`KNXClient: getConnectionStatus Timeout ${this._heartbeatFailures} out of ${this.max_HeartbeatFailures}`);
this._heartbeatFailures++;

@@ -674,2 +734,5 @@ if (this._heartbeatFailures >= this.max_HeartbeatFailures) {

}
getCurrentItemHandledByTheQueue() {
return this.currentItemHandledByTheQueue.expectedSeqNumberForACK;
}
incSeqNumber() {

@@ -687,2 +750,3 @@ this._clientTunnelSeqNumber++;

this.setTimer(KNXTimer.ACK, () => {
var _a, _b;
this._numFailedTelegramACK += 1;

@@ -694,8 +758,9 @@ if (this._numFailedTelegramACK > 2) {

this.emit(KNXClientEvents.error, timeoutErr);
this.sysLogger.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. ABORT sending datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. ABORT sending datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
}
else {
this.setTimerWaitingForACK(knxTunnelingRequest);
this.send(knxTunnelingRequest);
this.sysLogger.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. Retransmit datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. Retransmit datagram with seqNumber ${this.currentItemHandledByTheQueue
.expectedSeqNumberForACK} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
this.send(knxTunnelingRequest, knxTunnelingRequest, true, this.currentItemHandledByTheQueue
.expectedSeqNumberForACK);
}

@@ -705,2 +770,3 @@ }, KNXConstants_1.KNX_CONSTANTS.TUNNELING_REQUEST_TIMEOUT * 1000);

processInboundMessage(msg, rinfo) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
let sProcessInboundLog = '';

@@ -710,3 +776,3 @@ try {

sProcessInboundLog += ` srcAddress: ${JSON.stringify(rinfo)}`;
this.sysLogger.trace(`Received KNX packet: _processInboundMessage, ${sProcessInboundLog} ChannelID:${this._channelID}` ||
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.trace(`Received KNX packet: _processInboundMessage, ${sProcessInboundLog} ChannelID:${this._channelID}` ||
`??` +

@@ -743,3 +809,3 @@ ` Host:${this._options.ipAddr}:${this._options.ipPort}`);

this._clearToSend = true;
this.sysLogger.debug(`Received KNX packet: CONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.debug(`Received KNX packet: CONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this.emit(KNXClientEvents.connected, this._options);

@@ -750,3 +816,3 @@ this.startHeartBeat();

else if (knxHeader.service_type === KNXConstants_1.KNX_CONSTANTS.DISCONNECT_RESPONSE) {
this.sysLogger.debug(`Received KNX packet: DISCONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_c = this.sysLogger) === null || _c === void 0 ? void 0 : _c.debug(`Received KNX packet: DISCONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
if (this._connectionState !== ConncetionState.DISCONNECTING) {

@@ -762,3 +828,3 @@ this.emit(KNXClientEvents.error, new Error('Unexpected Disconnect Response.'));

}
this.sysLogger.error(`Received KNX packet: DISCONNECT_REQUEST, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_d = this.sysLogger) === null || _d === void 0 ? void 0 : _d.error(`Received KNX packet: DISCONNECT_REQUEST, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this._connectionState = ConncetionState.DISCONNECTING;

@@ -773,3 +839,3 @@ this.sendDisconnectResponseMessage(knxDisconnectRequest.channelID);

if (knxTunnelingRequest.channelID !== this._channelID) {
this.sysLogger.debug(`Received KNX packet: TUNNELING: L_DATA_IND, NOT FOR ME: MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_e = this.sysLogger) === null || _e === void 0 ? void 0 : _e.debug(`Received KNX packet: TUNNELING: L_DATA_IND, NOT FOR ME: MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
return;

@@ -779,6 +845,6 @@ }

const knxTunnelAck = KNXProtocol_1.default.newKNXTunnelingACK(knxTunnelingRequest.channelID, knxTunnelingRequest.seqCounter, KNXConstants_1.KNX_CONSTANTS.E_NO_ERROR);
this.send(knxTunnelAck);
this.send(knxTunnelAck, undefined, false, this.getSeqNumber());
}
catch (error) {
this.sysLogger.error(`Received KNX packet: TUNNELING: L_DATA_IND, ERROR BUOLDING THE TUNNELINK ACK: ${error.message} MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_f = this.sysLogger) === null || _f === void 0 ? void 0 : _f.error(`Received KNX packet: TUNNELING: L_DATA_IND, ERROR BUOLDING THE TUNNELINK ACK: ${error.message} MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
}

@@ -790,3 +856,3 @@ if (knxTunnelingRequest.cEMIMessage.msgCode ===

sDebugString += ` dstAddress: ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`;
this.sysLogger.debug(`Received KNX packet: TUNNELING: L_DATA_IND, ${sDebugString} ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_g = this.sysLogger) === null || _g === void 0 ? void 0 : _g.debug(`Received KNX packet: TUNNELING: L_DATA_IND, ${sDebugString} ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this.emit(KNXClientEvents.indication, knxTunnelingRequest, false);

@@ -796,3 +862,3 @@ }

CEMIConstants_1.default.L_DATA_CON) {
this.sysLogger.debug(`Received KNX packet: TUNNELING: L_DATA_CON, ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_h = this.sysLogger) === null || _h === void 0 ? void 0 : _h.debug(`Received KNX packet: TUNNELING: L_DATA_CON, ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
}

@@ -805,5 +871,6 @@ }

}
this.sysLogger.debug(`Received KNX packet: TUNNELING: TUNNELING_ACK, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_j = this.sysLogger) === null || _j === void 0 ? void 0 : _j.debug(`Received KNX packet: TUNNELING: TUNNELING_ACK, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
if (!this._options.suppress_ack_ldatareq) {
if (knxTunnelingAck.seqCounter === this.getSeqNumber()) {
if (knxTunnelingAck.seqCounter ===
this.getCurrentItemHandledByTheQueue()) {
this.clearTimer(KNXTimer.ACK);

@@ -813,6 +880,6 @@ this._numFailedTelegramACK = 0;

this.emit(KNXClientEvents.ackReceived, knxTunnelingAck, true);
this.sysLogger.debug(`Received KNX packet: TUNNELING: DELETED_TUNNELING_ACK FROM PENDING ACK's, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_k = this.sysLogger) === null || _k === void 0 ? void 0 : _k.debug(`Received KNX packet: TUNNELING: DELETED_TUNNELING_ACK FROM PENDING ACK's, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
}
else {
this.sysLogger.error(`Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = ${knxTunnelingAck.seqCounter}`);
(_l = this.sysLogger) === null || _l === void 0 ? void 0 : _l.error(`Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = ${knxTunnelingAck.seqCounter}, expecting ${this.getSeqNumber()}`);
}

@@ -829,3 +896,3 @@ }

sDebugString += ` dstAddress: ${knxRoutingInd.cEMIMessage.dstAddress.toString()}`;
this.sysLogger.debug(`Received KNX packet: ROUTING: L_DATA_IND, ${sDebugString} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_m = this.sysLogger) === null || _m === void 0 ? void 0 : _m.debug(`Received KNX packet: ROUTING: L_DATA_IND, ${sDebugString} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this.emit(KNXClientEvents.indication, knxRoutingInd, false);

@@ -835,3 +902,3 @@ }

CEMIConstants_1.default.L_DATA_CON) {
this.sysLogger.debug(`Received KNX packet: ROUTING: L_DATA_CON, Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_o = this.sysLogger) === null || _o === void 0 ? void 0 : _o.debug(`Received KNX packet: ROUTING: L_DATA_CON, Host:${this._options.ipAddr}:${this._options.ipPort}`);
}

@@ -843,3 +910,3 @@ }

KNXConstants_1.KNX_CONSTANTS.CONNECTIONSTATE_RESPONSE) {
this.sysLogger.debug(`Received KNX packet: CONNECTIONSTATE_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_p = this.sysLogger) === null || _p === void 0 ? void 0 : _p.debug(`Received KNX packet: CONNECTIONSTATE_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
const knxConnectionStateResponse = knxMessage;

@@ -864,22 +931,22 @@ if (knxConnectionStateResponse.status !==

catch (e) {
this.sysLogger.error(`Received KNX packet: Error processing inbound message: ${e.message} ${sProcessInboundLog} ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}. This means that KNX-Ultimate received a malformed Header or CEMI message from your KNX Gateway.`);
(_q = this.sysLogger) === null || _q === void 0 ? void 0 : _q.error(`Received KNX packet: Error processing inbound message: ${e.message} ${sProcessInboundLog} ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}. This means that KNX-Ultimate received a malformed Header or CEMI message from your KNX Gateway.`);
}
}
sendDescriptionRequestMessage() {
this.send(KNXProtocol_1.default.newKNXDescriptionRequest(new HPAI_1.default(this._options.localIPAddress)));
this.send(KNXProtocol_1.default.newKNXDescriptionRequest(new HPAI_1.default(this._options.localIPAddress)), undefined, false, this.getSeqNumber());
}
sendSearchRequestMessage() {
this.send(KNXProtocol_1.default.newKNXSearchRequest(new HPAI_1.default(this._options.localIPAddress, this._peerPort)));
this.send(KNXProtocol_1.default.newKNXSearchRequest(new HPAI_1.default(this._options.localIPAddress, this._peerPort)), undefined, false, this.getSeqNumber());
}
sendConnectRequestMessage(cri) {
this.send(KNXProtocol_1.default.newKNXConnectRequest(cri));
this.send(KNXProtocol_1.default.newKNXConnectRequest(cri), undefined, false, this.getSeqNumber());
}
sendConnectionStateRequestMessage(channelID) {
this.send(KNXProtocol_1.default.newKNXConnectionStateRequest(channelID));
this.send(KNXProtocol_1.default.newKNXConnectionStateRequest(channelID), undefined, false, this.getSeqNumber());
}
sendDisconnectRequestMessage(channelID) {
this.send(KNXProtocol_1.default.newKNXDisconnectRequest(channelID));
this.send(KNXProtocol_1.default.newKNXDisconnectRequest(channelID), undefined, false, this.getSeqNumber());
}
sendDisconnectResponseMessage(channelID, status = KNXConstants_1.ConnectionStatus.E_NO_ERROR) {
this.send(KNXProtocol_1.default.newKNXDisconnectResponse(channelID, status));
this.send(KNXProtocol_1.default.newKNXDisconnectResponse(channelID, status), undefined, false, this.getSeqNumber());
}

@@ -890,3 +957,3 @@ sendSecureSessionRequestMessage(cri) {

: KNXConstants_1.KNX_CONSTANTS.IPV4_UDP);
this.send(KNXProtocol_1.default.newKNXSecureSessionRequest(cri, oHPAI));
this.send(KNXProtocol_1.default.newKNXSecureSessionRequest(cri, oHPAI), undefined, false, this.getSeqNumber());
}

@@ -893,0 +960,0 @@ }

@@ -65,2 +65,3 @@ /// <reference types="node" />

localSocketAddress?: string;
KNXQueueSendIntervalMilliseconds?: number;
} & KNXLoggerOptions;

@@ -103,2 +104,4 @@ export declare function getDecodedKeyring(): string;

private clearAllTimers;
processKnxPacketQueueItem: () => Promise<void>;
handleKNXQueue: () => Promise<void>;
send(knxPacket: KNXPacket): void;

@@ -105,0 +108,0 @@ write(dstAddress: KNXAddress | string, data: any, dptid: string | number): void;

@@ -51,2 +51,3 @@ "use strict";

const utils_1 = require("./utils");
const limiter_1 = require("limiter");
var ConncetionState;

@@ -82,2 +83,8 @@ (function (ConncetionState) {

const jKNXSecureKeyring = '';
let limiter = new limiter_1.RateLimiter({
tokensPerInterval: 1,
interval: 25,
});
const commandQueue = [];
let exitProcessingKNXQueueLoop = false;
const optionsDefaults = {

@@ -88,3 +95,3 @@ physAddr: '15.15.200',

ipPort: 3671,
hostProtocol: 'TunnelUDP',
hostProtocol: 'Multicast',
isSecureKNXEnabled: false,

@@ -97,2 +104,3 @@ suppress_ack_ldatareq: false,

jKNXSecureKeyring: {},
KNXQueueSendIntervalMilliseconds: 25,
};

@@ -115,4 +123,83 @@ function getDecodedKeyring() {

constructor(options) {
var _a;
super();
this.processKnxPacketQueueItem = async () => {
var _a, _b, _c, _d, _e;
const knxPacket = commandQueue.pop();
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: processKnxPacketQueueItem: Processing queued KNX. commandQueue.length: ${commandQueue.length} ${knxPacket.header.service_type}`);
if (knxPacket instanceof KNXConnectRequest_1.default) {
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.debug(`Sending KNX packet: ${knxPacket.constructor.name} Host:${this._peerHost}:${this._peerPort}`);
}
if (knxPacket instanceof KNXTunnelingRequest_1.default ||
knxPacket instanceof KNXRoutingIndication_1.default) {
let sTPCI = '';
if (knxPacket.cEMIMessage.npdu.isGroupRead) {
sTPCI = 'Read';
}
if (knxPacket.cEMIMessage.npdu.isGroupResponse) {
sTPCI = 'Response';
}
if (knxPacket.cEMIMessage.npdu.isGroupWrite) {
sTPCI = 'Write';
}
let sDebugString = `Data: ${JSON.stringify(knxPacket.cEMIMessage.npdu)}`;
sDebugString += ` srcAddress: ${knxPacket.cEMIMessage.srcAddress.toString()}`;
sDebugString += ` dstAddress: ${knxPacket.cEMIMessage.dstAddress.toString()}`;
(_c = this.sysLogger) === null || _c === void 0 ? void 0 : _c.debug(`Sending KNX packet: ${knxPacket.constructor.name} ${sDebugString} Host:${this._peerHost}:${this._peerPort} channelID:${knxPacket.channelID} seqCounter:${knxPacket.seqCounter} Dest:${knxPacket.cEMIMessage.dstAddress.toString()}`, ` Data:${knxPacket.cEMIMessage.npdu.dataValue.toString('hex')} TPCI:${sTPCI}`);
}
if (this._options.hostProtocol === 'Multicast' ||
this._options.hostProtocol === 'TunnelUDP') {
try {
;
this._clientSocket.send(knxPacket.toBuffer(), this._peerPort, this._peerHost, (err) => {
var _a;
if (err) {
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`Sending KNX packet: Send UDP sending error: ${err.message}`);
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
(_d = this.sysLogger) === null || _d === void 0 ? void 0 : _d.error(`Sending KNX packet: Send UDP Catch error: ${error.message} ${typeof knxPacket} seqCounter:${knxPacket.seqCounter || ''}`);
this.emit(KNXClientEvents.error, error);
}
}
else {
try {
;
this._clientSocket.write(knxPacket.toBuffer(), (err) => {
var _a;
if (err) {
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`Sending KNX packet: Send TCP sending error: ${err.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
(_e = this.sysLogger) === null || _e === void 0 ? void 0 : _e.error(`Sending KNX packet: Send TCP Catch error: ${error.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, error);
}
}
};
this.handleKNXQueue = async () => {
var _a, _b, _c, _d, _e;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: handleKNXQueue: Start Processing queued KNX.`);
do {
const remainingRequests = await limiter.removeTokens(1);
if (commandQueue.length > 0 && this.clearToSend) {
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.debug(`\n\nKNXClient: START.`);
await this.processKnxPacketQueueItem();
(_c = this.sysLogger) === null || _c === void 0 ? void 0 : _c.debug(`KNXClient: END.`);
}
else if (!this.clearToSend) {
(_d = this.sysLogger) === null || _d === void 0 ? void 0 : _d.warn(`KNXClient: NOT CLEAR TO SEND!`);
}
} while (exitProcessingKNXQueueLoop === false);
(_e = this.sysLogger) === null || _e === void 0 ? void 0 : _e.debug(`KNXClient: handleKNXQueue: Stop Processing queued KNX.`);
};
this.handleKNXQueue();
this.timers = new Map();
exitProcessingKNXQueueLoop = false;
if (options === undefined) {

@@ -142,2 +229,6 @@ options = optionsDefaults;

this.jKNXSecureKeyring = this._options.jKNXSecureKeyring;
limiter = new limiter_1.RateLimiter({
tokensPerInterval: 1,
interval: this._options.KNXQueueSendIntervalMilliseconds,
});
this.on('error', (error) => { });

@@ -151,3 +242,3 @@ if (typeof this._options.physAddr === 'string') {

catch (error) {
this.sysLogger.error(`ipAddressHelper.getLocalAddress:${error.message}`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`ipAddressHelper.getLocalAddress:${error.message}`);
throw error;

@@ -161,2 +252,3 @@ }

this._clientSocket.bind({ port: null, address: this._options.localIPAddress }, () => {
var _a;
try {

@@ -170,3 +262,3 @@ ;

catch (error) {
this.sysLogger.error(`UDP: Error setting SetTTL ${error.message}` || '');
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`UDP: Error setting SetTTL ${error.message}` || '');
}

@@ -196,2 +288,3 @@ });

this._clientSocket.bind(this._peerPort, () => {
var _a, _b;
const client = this._clientSocket;

@@ -203,3 +296,3 @@ try {

catch (error) {
this.sysLogger.error(`Multicast: Error setting SetTTL ${error.message}` ||
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`Multicast: Error setting SetTTL ${error.message}` ||
'');

@@ -211,3 +304,3 @@ }

catch (err) {
this.sysLogger.error('Multicast: cannot add membership (%s)', err);
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.error('Multicast: cannot add membership (%s)', err);
this.emit(KNXClientEvents.error, err);

@@ -225,2 +318,3 @@ }

getKNXDataBuffer(data, dptid) {
var _a;
if (typeof dptid === 'number') {

@@ -233,3 +327,3 @@ dptid = dptid.toString();

const isSixBits = adpu.bitlength <= 6;
this.sysLogger.trace(`isSixBits:${isSixBits} Includes (should be = isSixBits):${[
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.trace(`isSixBits:${isSixBits} Includes (should be = isSixBits):${[
1, 2, 3, 5, 9, 10, 11, 14, 18,

@@ -260,6 +354,7 @@ ].includes(iDatapointType)} ADPU BitLength:${adpu.bitlength}`);

setTimer(type, cb, delay) {
var _a;
if (this.timers.has(type)) {
clearTimeout(this.timers.get(type));
this.timers.delete(type);
this.sysLogger.warn(`Timer "${type}" was already running`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.warn(`Timer "${type}" was already running`);
}

@@ -285,55 +380,5 @@ this.timers.set(type, setTimeout(() => {

send(knxPacket) {
if (knxPacket instanceof KNXConnectRequest_1.default) {
this.sysLogger.debug(`Sending KNX packet: ${knxPacket.constructor.name} Host:${this._peerHost}:${this._peerPort}`);
}
if (knxPacket instanceof KNXTunnelingRequest_1.default ||
knxPacket instanceof KNXRoutingIndication_1.default) {
let sTPCI = '';
if (knxPacket.cEMIMessage.npdu.isGroupRead) {
sTPCI = 'Read';
}
if (knxPacket.cEMIMessage.npdu.isGroupResponse) {
sTPCI = 'Response';
}
if (knxPacket.cEMIMessage.npdu.isGroupWrite) {
sTPCI = 'Write';
}
let sDebugString = `Data: ${JSON.stringify(knxPacket.cEMIMessage.npdu)}`;
sDebugString += ` srcAddress: ${knxPacket.cEMIMessage.srcAddress.toString()}`;
sDebugString += ` dstAddress: ${knxPacket.cEMIMessage.dstAddress.toString()}`;
this.sysLogger.debug(`Sending KNX packet: ${knxPacket.constructor.name} ${sDebugString} Host:${this._peerHost}:${this._peerPort} channelID:${knxPacket.channelID} seqCounter:${knxPacket.seqCounter} Dest:${knxPacket.cEMIMessage.dstAddress.toString()}`, ` Data:${knxPacket.cEMIMessage.npdu.dataValue.toString('hex')} TPCI:${sTPCI}`);
}
if (this._options.hostProtocol === 'Multicast' ||
this._options.hostProtocol === 'TunnelUDP') {
try {
;
this._clientSocket.send(knxPacket.toBuffer(), this._peerPort, this._peerHost, (err) => {
if (err) {
this.sysLogger.error(`Sending KNX packet: Send UDP sending error: ${err.message}`);
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
this.sysLogger.error(`Sending KNX packet: Send UDP Catch error: ${error.message} ${typeof knxPacket} seqCounter:${knxPacket.seqCounter || ''}`);
this.emit(KNXClientEvents.error, error);
}
}
else {
try {
;
this._clientSocket.write(knxPacket.toBuffer(), (err) => {
if (err) {
this.sysLogger.error(`Sending KNX packet: Send TCP sending error: ${err.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, err);
}
});
}
catch (error) {
this.sysLogger.error(`Sending KNX packet: Send TCP Catch error: ${error.message}` ||
'Undef error');
this.emit(KNXClientEvents.error, error);
}
}
var _a;
commandQueue.unshift(knxPacket);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: ADDED PACKET TO COMMANDQUEUE. Len: ${commandQueue.length}`);
}

@@ -439,6 +484,7 @@ write(dstAddress, data, dptid) {

writeRaw(dstAddress, rawDataBuffer, bitlength) {
var _a;
if (this._connectionState !== ConncetionState.CONNECTED)
throw new Error('The socket is not connected. Unable to access the KNX BUS');
if (!Buffer.isBuffer(rawDataBuffer)) {
this.sysLogger.error('KNXClient: writeRaw: Value must be a buffer! ');
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error('KNXClient: writeRaw: Value must be a buffer! ');
return;

@@ -577,3 +623,5 @@ }

async closeSocket() {
exitProcessingKNXQueueLoop = true;
return new Promise((resolve) => {
var _a;
if (!this._clientSocket)

@@ -585,9 +633,15 @@ return;

};
if (this._options.hostProtocol === 'TunnelTCP') {
;
this._clientSocket.destroy();
try {
if (this._options.hostProtocol === 'TunnelTCP') {
;
this._clientSocket.destroy();
}
else {
;
this._clientSocket.close(cb);
}
}
else {
;
this._clientSocket.close(cb);
catch (error) {
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`KNXClient: into async closeSocket(): ${error.stack}`);
resolve();
}

@@ -597,2 +651,3 @@ });

async Disconnect() {
var _a;
if (this._clientSocket === null) {

@@ -607,3 +662,3 @@ throw new Error('No client socket defined');

if (this._channelID === null) {
this.sysLogger.debug(`KNXClient: into Disconnect(), channel id is not defined so skip disconnect packet and close socket`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: into Disconnect(), channel id is not defined so skip disconnect packet and close socket`);
await this.closeSocket();

@@ -623,3 +678,4 @@ return;

async setDisconnected(_sReason = '') {
this.sysLogger.debug(`KNXClient: called _setDisconnected ${this._options.ipAddr}:${this._options.ipPort} ${_sReason}`);
var _a;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.debug(`KNXClient: called _setDisconnected ${this._options.ipAddr}:${this._options.ipPort} ${_sReason}`);
this._connectionState = ConncetionState.DISCONNECTED;

@@ -642,3 +698,4 @@ this.clearAllTimers();

this.setTimer(KNXTimer.CONNECTION_STATE, () => {
this.sysLogger.error(`KNXClient: getConnectionStatus Timeout ${this._heartbeatFailures} out of ${this.max_HeartbeatFailures}`);
var _a;
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`KNXClient: getConnectionStatus Timeout ${this._heartbeatFailures} out of ${this.max_HeartbeatFailures}`);
this._heartbeatFailures++;

@@ -672,2 +729,3 @@ if (this._heartbeatFailures >= this.max_HeartbeatFailures) {

this.setTimer(KNXTimer.ACK, () => {
var _a, _b;
this._numFailedTelegramACK += 1;

@@ -679,3 +737,3 @@ if (this._numFailedTelegramACK > 2) {

this.emit(KNXClientEvents.error, timeoutErr);
this.sysLogger.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. ABORT sending datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. ABORT sending datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
}

@@ -685,3 +743,3 @@ else {

this.send(knxTunnelingRequest);
this.sysLogger.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. Retransmit datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.error(`KNXClient: _setTimerWaitingForACK: ${timeoutErr.message || 'Undef error'} no ACK received. Retransmit datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`);
}

@@ -691,2 +749,3 @@ }, KNXConstants_1.KNX_CONSTANTS.TUNNELING_REQUEST_TIMEOUT * 1000);

processInboundMessage(msg, rinfo) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
let sProcessInboundLog = '';

@@ -696,3 +755,3 @@ try {

sProcessInboundLog += ` srcAddress: ${JSON.stringify(rinfo)}`;
this.sysLogger.trace(`Received KNX packet: _processInboundMessage, ${sProcessInboundLog} ChannelID:${this._channelID}` ||
(_a = this.sysLogger) === null || _a === void 0 ? void 0 : _a.trace(`Received KNX packet: _processInboundMessage, ${sProcessInboundLog} ChannelID:${this._channelID}` ||
`??` +

@@ -729,3 +788,3 @@ ` Host:${this._options.ipAddr}:${this._options.ipPort}`);

this._clearToSend = true;
this.sysLogger.debug(`Received KNX packet: CONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_b = this.sysLogger) === null || _b === void 0 ? void 0 : _b.debug(`Received KNX packet: CONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this.emit(KNXClientEvents.connected, this._options);

@@ -736,3 +795,3 @@ this.startHeartBeat();

else if (knxHeader.service_type === KNXConstants_1.KNX_CONSTANTS.DISCONNECT_RESPONSE) {
this.sysLogger.debug(`Received KNX packet: DISCONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_c = this.sysLogger) === null || _c === void 0 ? void 0 : _c.debug(`Received KNX packet: DISCONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
if (this._connectionState !== ConncetionState.DISCONNECTING) {

@@ -748,3 +807,3 @@ this.emit(KNXClientEvents.error, new Error('Unexpected Disconnect Response.'));

}
this.sysLogger.error(`Received KNX packet: DISCONNECT_REQUEST, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_d = this.sysLogger) === null || _d === void 0 ? void 0 : _d.error(`Received KNX packet: DISCONNECT_REQUEST, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this._connectionState = ConncetionState.DISCONNECTING;

@@ -759,3 +818,3 @@ this.sendDisconnectResponseMessage(knxDisconnectRequest.channelID);

if (knxTunnelingRequest.channelID !== this._channelID) {
this.sysLogger.debug(`Received KNX packet: TUNNELING: L_DATA_IND, NOT FOR ME: MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_e = this.sysLogger) === null || _e === void 0 ? void 0 : _e.debug(`Received KNX packet: TUNNELING: L_DATA_IND, NOT FOR ME: MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
return;

@@ -768,3 +827,3 @@ }

catch (error) {
this.sysLogger.error(`Received KNX packet: TUNNELING: L_DATA_IND, ERROR BUOLDING THE TUNNELINK ACK: ${error.message} MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_f = this.sysLogger) === null || _f === void 0 ? void 0 : _f.error(`Received KNX packet: TUNNELING: L_DATA_IND, ERROR BUOLDING THE TUNNELINK ACK: ${error.message} MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
}

@@ -776,3 +835,3 @@ if (knxTunnelingRequest.cEMIMessage.msgCode ===

sDebugString += ` dstAddress: ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`;
this.sysLogger.debug(`Received KNX packet: TUNNELING: L_DATA_IND, ${sDebugString} ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_g = this.sysLogger) === null || _g === void 0 ? void 0 : _g.debug(`Received KNX packet: TUNNELING: L_DATA_IND, ${sDebugString} ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this.emit(KNXClientEvents.indication, knxTunnelingRequest, false);

@@ -782,3 +841,3 @@ }

CEMIConstants_1.default.L_DATA_CON) {
this.sysLogger.debug(`Received KNX packet: TUNNELING: L_DATA_CON, ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_h = this.sysLogger) === null || _h === void 0 ? void 0 : _h.debug(`Received KNX packet: TUNNELING: L_DATA_CON, ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
}

@@ -791,3 +850,3 @@ }

}
this.sysLogger.debug(`Received KNX packet: TUNNELING: TUNNELING_ACK, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_j = this.sysLogger) === null || _j === void 0 ? void 0 : _j.debug(`Received KNX packet: TUNNELING: TUNNELING_ACK, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
if (!this._options.suppress_ack_ldatareq) {

@@ -799,6 +858,6 @@ if (knxTunnelingAck.seqCounter === this.getSeqNumber()) {

this.emit(KNXClientEvents.ackReceived, knxTunnelingAck, true);
this.sysLogger.debug(`Received KNX packet: TUNNELING: DELETED_TUNNELING_ACK FROM PENDING ACK's, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_k = this.sysLogger) === null || _k === void 0 ? void 0 : _k.debug(`Received KNX packet: TUNNELING: DELETED_TUNNELING_ACK FROM PENDING ACK's, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`);
}
else {
this.sysLogger.error(`Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = ${knxTunnelingAck.seqCounter}`);
(_l = this.sysLogger) === null || _l === void 0 ? void 0 : _l.error(`Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = ${knxTunnelingAck.seqCounter}`);
}

@@ -815,3 +874,3 @@ }

sDebugString += ` dstAddress: ${knxRoutingInd.cEMIMessage.dstAddress.toString()}`;
this.sysLogger.debug(`Received KNX packet: ROUTING: L_DATA_IND, ${sDebugString} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_m = this.sysLogger) === null || _m === void 0 ? void 0 : _m.debug(`Received KNX packet: ROUTING: L_DATA_IND, ${sDebugString} Host:${this._options.ipAddr}:${this._options.ipPort}`);
this.emit(KNXClientEvents.indication, knxRoutingInd, false);

@@ -821,3 +880,3 @@ }

CEMIConstants_1.default.L_DATA_CON) {
this.sysLogger.debug(`Received KNX packet: ROUTING: L_DATA_CON, Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_o = this.sysLogger) === null || _o === void 0 ? void 0 : _o.debug(`Received KNX packet: ROUTING: L_DATA_CON, Host:${this._options.ipAddr}:${this._options.ipPort}`);
}

@@ -829,3 +888,3 @@ }

KNXConstants_1.KNX_CONSTANTS.CONNECTIONSTATE_RESPONSE) {
this.sysLogger.debug(`Received KNX packet: CONNECTIONSTATE_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
(_p = this.sysLogger) === null || _p === void 0 ? void 0 : _p.debug(`Received KNX packet: CONNECTIONSTATE_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`);
const knxConnectionStateResponse = knxMessage;

@@ -850,3 +909,3 @@ if (knxConnectionStateResponse.status !==

catch (e) {
this.sysLogger.error(`Received KNX packet: Error processing inbound message: ${e.message} ${sProcessInboundLog} ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}. This means that KNX-Ultimate received a malformed Header or CEMI message from your KNX Gateway.`);
(_q = this.sysLogger) === null || _q === void 0 ? void 0 : _q.error(`Received KNX packet: Error processing inbound message: ${e.message} ${sProcessInboundLog} ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}. This means that KNX-Ultimate received a malformed Header or CEMI message from your KNX Gateway.`);
}

@@ -853,0 +912,0 @@ }

# [3.0.0-beta.0](https://github.com/Supergiovane/KNXUltimate/compare/v2.3.5...v3.0.0-beta.0) (2024-09-08)
### Features
* transparent KNX queue. The sent telegrams are now queued and transmitted to the bus by obeying the time interval specified by the new property "KNXQueueSendIntervalMilliseconds" ([93a65c9](https://github.com/Supergiovane/KNXUltimate/commit/93a65c97c426977b69b8c4f3044755229ad89b3a))
## [2.3.5](https://github.com/Supergiovane/KNXUltimate/compare/v2.3.4...v2.3.5) (2024-07-08)

@@ -4,0 +11,0 @@

{
"name": "knxultimate",
"description": "KNX IP protocol implementation for Node. This is the ENGINE of Node-Red KNX-Ultimate node.",
"version": "2.3.5",
"version": "3.0.0-beta.0",
"main": "./build/index.js",

@@ -20,3 +20,4 @@ "engines": {

"test-connection": "",
"release": "read -p 'GITHUB_TOKEN: ' GITHUB_TOKEN && export GITHUB_TOKEN=$GITHUB_TOKEN && release-it"
"release": "read -p 'GITHUB_TOKEN: ' GITHUB_TOKEN && export GITHUB_TOKEN=$GITHUB_TOKEN && release-it",
"betarelease": "read -p 'GITHUB_TOKEN: ' GITHUB_TOKEN && export GITHUB_TOKEN=$GITHUB_TOKEN && release-it major --preRelease=beta"
},

@@ -49,3 +50,3 @@ "release-it": {

"author": {
"name": "Max Supergiovane",
"name": "Massimo 'Supergiovane' Saccani",
"email": "maxsupergiovane@icloud.com"

@@ -55,3 +56,3 @@ },

{
"name": "Max Supergiovane",
"name": "Massimo 'Supergiovane' Saccani",
"email": "maxsupergiovane@icloud.com"

@@ -75,2 +76,3 @@ },

"crypto-js": "4.2.0",
"limiter": "2.1.0",
"log-driver": "1.2.7",

@@ -77,0 +79,0 @@ "mkdirp": "3.0.1",

@@ -10,9 +10,14 @@ ![Logo](img/logo-big.png)

[![Youtube][youtube-image]][youtube-url]
[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square)](https://www.paypal.me/techtoday)
Control your KNX intallation via Node.js!
> This is the official engine of Node-Red node KNX-Ultimate (<https://flows.nodered.org/node/node-red-contrib-knx-ultimate>)
> I had many users asking for a node.js release of that engine, so here is it.
Control your KNX intallation via Node.js!
This is the official engine of Node-Red's node [node-red-contrib-knx-ultimate](https://flows.nodered.org/node/node-red-contrib-knx-ultimate)
Many of you asked for a node.js release of that engine, so i decided to create this package.
If you enjoy my work developing this package, do today a kind thing for someone too. This will be the reward for my work.
<br/>
![Logo](img/readmemain.png)
## CHANGELOG

@@ -48,4 +53,4 @@

| interface (string) | Specifies the local eth interface to be used to connect to the KNX Bus.|
| KNXQueueSendIntervalMilliseconds | The KNX standard has a maximum transmit rate to the BUS, of about 1 telegram each 25ms (to stay safe). In case you've a lot of traffic on the BUS, you can increase this value, expressed in milliseconds. Be careful, because if you set it too high, the KNX engine could send a telegram with flag 'repeat', because the ACK from the device is coming too late.|
## SUPPORTED DATAPOINTS

@@ -52,0 +57,0 @@

@@ -29,2 +29,3 @@ // Made with love by Supergiovane

import { wait } from './utils'
import { RateLimiter } from 'limiter'

@@ -109,2 +110,4 @@ export enum ConncetionState {

localSocketAddress?: string
// ** Local queue interval between each KNX telegram. Default is 1 telegram each 25ms
KNXQueueSendIntervalMilliseconds?: number
} & KNXLoggerOptions

@@ -117,3 +120,3 @@

ipPort: 3671,
hostProtocol: 'TunnelUDP',
hostProtocol: 'Multicast',
isSecureKNXEnabled: false,

@@ -126,2 +129,3 @@ suppress_ack_ldatareq: false,

jKNXSecureKeyring: {},
KNXQueueSendIntervalMilliseconds: 25,
}

@@ -150,2 +154,8 @@

interface KNXQueueItem {
knxPacket: KNXPacket
ACK: KNXTunnelingRequest
expectedSeqNumberForACK: number
}
export default class KNXClient extends TypedEventEmitter<KNXClientEventCallbacks> {

@@ -186,6 +196,16 @@ private _channelID: number

private limiter: RateLimiter
private commandQueue: Array<KNXQueueItem> = []
private exitProcessingKNXQueueLoop: boolean
private currentItemHandledByTheQueue: KNXQueueItem
constructor(options: KNXClientOptions) {
super()
this.timers = new Map()
// This is the KNX telegram's queue list
this.commandQueue = []
this.exitProcessingKNXQueueLoop = false

@@ -220,3 +240,7 @@ if (options === undefined) {

this.jKNXSecureKeyring = this._options.jKNXSecureKeyring
// Reionfigura il rate limiter per coda KNX
this.limiter = new RateLimiter({
tokensPerInterval: 1,
interval: this._options.KNXQueueSendIntervalMilliseconds,
})
// add an empty error listener, without this

@@ -235,3 +259,3 @@ // every "error" emitted would throw an unhandled exception

} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`ipAddressHelper.getLocalAddress:${error.message}`,

@@ -259,3 +283,3 @@ )

} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`UDP: Error setting SetTTL ${error.message}` || '',

@@ -311,3 +335,3 @@ )

} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`Multicast: Error setting SetTTL ${error.message}` ||

@@ -323,3 +347,3 @@ '',

} catch (err) {
this.sysLogger.error(
this.sysLogger?.error(
'Multicast: cannot add membership (%s)',

@@ -360,3 +384,3 @@ err,

this.sysLogger.trace(
this.sysLogger?.trace(
`isSixBits:${isSixBits} Includes (should be = isSixBits):${[

@@ -398,3 +422,3 @@ 1, 2, 3, 5, 9, 10, 11, 14, 18,

// TODO: should we throw error?
this.sysLogger.warn(`Timer "${type}" was already running`)
this.sysLogger?.warn(`Timer "${type}" was already running`)
}

@@ -429,39 +453,42 @@

/**
* Write knxPacket to socket
*/
send(knxPacket: KNXPacket): void {
if (knxPacket instanceof KNXConnectRequest) {
this.sysLogger.debug(
`Sending KNX packet: ${knxPacket.constructor.name} Host:${this._peerHost}:${this._peerPort}`,
processKnxPacketQueueItem = async (_knxPacket: KNXPacket) => {
// await new Promise((f) => {
// setTimeout(f, 2000)
// }) // For debugging
this.sysLogger?.debug(
`KNXClient: processKnxPacketQueueItem: Processing queued KNX. commandQueue.length: ${this.commandQueue.length} ${_knxPacket.header.service_type}`,
)
if (_knxPacket instanceof KNXConnectRequest) {
this.sysLogger?.debug(
`Sending KNX packet: ${_knxPacket.constructor.name} Host:${this._peerHost}:${this._peerPort}`,
)
}
if (
knxPacket instanceof KNXTunnelingRequest ||
knxPacket instanceof KNXRoutingIndication
_knxPacket instanceof KNXTunnelingRequest ||
_knxPacket instanceof KNXRoutingIndication
) {
let sTPCI = ''
if (knxPacket.cEMIMessage.npdu.isGroupRead) {
if (_knxPacket.cEMIMessage.npdu.isGroupRead) {
sTPCI = 'Read'
}
if (knxPacket.cEMIMessage.npdu.isGroupResponse) {
if (_knxPacket.cEMIMessage.npdu.isGroupResponse) {
sTPCI = 'Response'
}
if (knxPacket.cEMIMessage.npdu.isGroupWrite) {
if (_knxPacket.cEMIMessage.npdu.isGroupWrite) {
sTPCI = 'Write'
}
let sDebugString = `Data: ${JSON.stringify(knxPacket.cEMIMessage.npdu)}`
sDebugString += ` srcAddress: ${knxPacket.cEMIMessage.srcAddress.toString()}`
sDebugString += ` dstAddress: ${knxPacket.cEMIMessage.dstAddress.toString()}`
let sDebugString = `Data: ${JSON.stringify(_knxPacket.cEMIMessage.npdu)}`
sDebugString += ` srcAddress: ${_knxPacket.cEMIMessage.srcAddress.toString()}`
sDebugString += ` dstAddress: ${_knxPacket.cEMIMessage.dstAddress.toString()}`
this.sysLogger.debug(
this.sysLogger?.debug(
`Sending KNX packet: ${
knxPacket.constructor.name
_knxPacket.constructor.name
} ${sDebugString} Host:${this._peerHost}:${
this._peerPort
} channelID:${(knxPacket as KNXTunnelingRequest).channelID} seqCounter:${
(knxPacket as KNXTunnelingRequest).seqCounter
} Dest:${knxPacket.cEMIMessage.dstAddress.toString()}`,
` Data:${knxPacket.cEMIMessage.npdu.dataValue.toString(
} channelID:${(_knxPacket as KNXTunnelingRequest).channelID} seqCounter:${
(_knxPacket as KNXTunnelingRequest).seqCounter
} Dest:${_knxPacket.cEMIMessage.dstAddress.toString()}`,
` Data:${_knxPacket.cEMIMessage.npdu.dataValue.toString(
'hex',

@@ -478,3 +505,3 @@ )} TPCI:${sTPCI}`,

;(this._clientSocket as UDPSocket).send(
knxPacket.toBuffer(),
_knxPacket.toBuffer(),
this._peerPort,

@@ -484,3 +511,3 @@ this._peerHost,

if (err) {
this.sysLogger.error(
this.sysLogger?.error(
`Sending KNX packet: Send UDP sending error: ${err.message}`,

@@ -493,7 +520,7 @@ )

} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`Sending KNX packet: Send UDP Catch error: ${
error.message
} ${typeof knxPacket} seqCounter:${
(knxPacket as any).seqCounter || ''
} ${typeof _knxPacket} seqCounter:${
(_knxPacket as any).seqCounter || ''
}`,

@@ -506,6 +533,6 @@ )

;(this._clientSocket as TCPSocket).write(
knxPacket.toBuffer(),
_knxPacket.toBuffer(),
(err) => {
if (err) {
this.sysLogger.error(
this.sysLogger?.error(
`Sending KNX packet: Send TCP sending error: ${err.message}` ||

@@ -519,3 +546,3 @@ 'Undef error',

} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`Sending KNX packet: Send TCP Catch error: ${error.message}` ||

@@ -529,2 +556,56 @@ 'Undef error',

handleKNXQueue = async () => {
this.sysLogger?.debug(
`KNXClient: handleKNXQueue: Start Processing queued KNX.`,
)
do {
// Limiter: limits max telegrams per second
const remainingRequests = await this.limiter.removeTokens(1)
if (this.commandQueue.length > 0 && this._clearToSend) {
this.sysLogger?.debug(`\n\nKNXClient: START.`)
const item = this.commandQueue.pop()
this.currentItemHandledByTheQueue = item
if (item.ACK !== undefined) {
await this.processKnxPacketQueueItem(item.knxPacket)
this.setTimerWaitingForACK(item.ACK)
} else {
await this.processKnxPacketQueueItem(item.knxPacket)
}
this.sysLogger?.debug(`KNXClient: END.`)
} // else if (!this.clearToSend) {
// this.sysLogger?.warn(`KNXClient: NOT CLEAR TO SEND!`)
// }
if (this.exitProcessingKNXQueueLoop) return
} while (this.exitProcessingKNXQueueLoop === false)
this.sysLogger?.debug(
`KNXClient: handleKNXQueue: Stop Processing queued KNX.`,
)
}
/**
* Write knxPacket to socket
*/
send(
_knxPacket: KNXPacket,
_ACK: KNXTunnelingRequest,
_priority: boolean,
_expectedSeqNumberForACK: number,
): void {
const toBeAdded: KNXQueueItem = {
knxPacket: _knxPacket,
ACK: _ACK,
expectedSeqNumberForACK: _expectedSeqNumberForACK,
}
if (_priority) {
this.commandQueue.push(toBeAdded)
this._clearToSend = true
} else {
this.commandQueue.unshift(toBeAdded) // Put the item as last to be sent
}
this.sysLogger?.debug(
`KNXClient: ADDED TELEGRAM TO COMMANDQUEUE. Len: ${this.commandQueue.length}`,
)
}
/** Sends a WRITE telegram to the BUS.

@@ -570,3 +651,3 @@ * `dstAddress` is the group address (for example "0/0/1"),

KNXProtocol.newKNXRoutingIndication(cEMIMessage)
this.send(knxPacketRequest)
this.send(knxPacketRequest, undefined, false, this.getSeqNumber())
// 06/12/2021 Multivast automaticalli echoes telegrams

@@ -594,4 +675,8 @@ } else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest)
this.send(knxPacketRequest)
this.send(
knxPacketRequest,
knxPacketRequest,
false,
this.getSeqNumber(),
)
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false

@@ -644,3 +729,3 @@ if (this._options.localEchoInTunneling)

KNXProtocol.newKNXRoutingIndication(cEMIMessage)
this.send(knxPacketRequest)
this.send(knxPacketRequest, undefined, false, this.getSeqNumber())
// 06/12/2021 Multivast automaticalli echoes telegrams

@@ -668,4 +753,8 @@ } else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest)
this.send(knxPacketRequest)
this.send(
knxPacketRequest,
knxPacketRequest,
false,
this.getSeqNumber(),
)
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false

@@ -708,3 +797,3 @@ if (this._options.localEchoInTunneling)

KNXProtocol.newKNXRoutingIndication(cEMIMessage)
this.send(knxPacketRequest)
this.send(knxPacketRequest, undefined, false, this.getSeqNumber())
// 06/12/2021 Multivast automaticalli echoes telegrams

@@ -732,4 +821,8 @@ } else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest)
this.send(knxPacketRequest)
this.send(
knxPacketRequest,
knxPacketRequest,
false,
this.getSeqNumber(),
)
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false

@@ -760,3 +853,3 @@ if (this._options.localEchoInTunneling)

if (!Buffer.isBuffer(rawDataBuffer)) {
this.sysLogger.error(
this.sysLogger?.error(
'KNXClient: writeRaw: Value must be a buffer! ',

@@ -807,3 +900,3 @@ )

KNXProtocol.newKNXRoutingIndication(cEMIMessage)
this.send(knxPacketRequest)
this.send(knxPacketRequest, undefined, false, this.getSeqNumber())
// 06/12/2021 Multivast automaticalli echoes telegrams

@@ -832,4 +925,8 @@ } else {

if (!this._options.suppress_ack_ldatareq)
this.setTimerWaitingForACK(knxPacketRequest)
this.send(knxPacketRequest)
this.send(
knxPacketRequest,
knxPacketRequest,
false,
this.getSeqNumber(),
)
// 06/12/2021 Echo the sent telegram. Last parameter is the echo true/false

@@ -943,2 +1040,3 @@ if (this._options.localEchoInTunneling)

this.handleKNXQueue() // Start the KNX queue processing loop
this._connectionState = ConncetionState.CONNECTING

@@ -1009,2 +1107,3 @@ this._numFailedTelegramACK = 0 // 25/12/2021 Reset the failed ACK counter

private async closeSocket() {
this.exitProcessingKNXQueueLoop = true // Exits KNX processing queue loop
return new Promise<void>((resolve) => {

@@ -1015,3 +1114,3 @@ // already closed

const cb = () => {
this._clientSocket = null
// this._clientSocket = null
resolve()

@@ -1028,3 +1127,3 @@ }

} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`KNXClient: into async closeSocket(): ${error.stack}`,

@@ -1041,2 +1140,3 @@ )

async Disconnect() {
this.exitProcessingKNXQueueLoop = true // Exits KNX processing queue loop
if (this._clientSocket === null) {

@@ -1058,3 +1158,3 @@ throw new Error('No client socket defined')

// 11/10/2022 Close the socket
this.sysLogger.debug(
this.sysLogger?.debug(
`KNXClient: into Disconnect(), channel id is not defined so skip disconnect packet and close socket`,

@@ -1091,3 +1191,3 @@ )

private async setDisconnected(_sReason = '') {
this.sysLogger.debug(
this.sysLogger?.debug(
`KNXClient: called _setDisconnected ${this._options.ipAddr}:${this._options.ipPort} ${_sReason}`,

@@ -1136,3 +1236,3 @@ )

() => {
this.sysLogger.error(
this.sysLogger?.error(
`KNXClient: getConnectionStatus Timeout ${this._heartbeatFailures} out of ${this.max_HeartbeatFailures}`,

@@ -1171,2 +1271,6 @@ )

private getCurrentItemHandledByTheQueue() {
return this.currentItemHandledByTheQueue.expectedSeqNumberForACK
}
/**

@@ -1215,3 +1319,3 @@ * Increment the tunneling sequence number

this.emit(KNXClientEvents.error, timeoutErr)
this.sysLogger.error(
this.sysLogger?.error(
`KNXClient: _setTimerWaitingForACK: ${

@@ -1223,9 +1327,17 @@ timeoutErr.message || 'Undef error'

// 26/12/2021 // If no ACK received, resend the datagram once with the same sequence number
this.setTimerWaitingForACK(knxTunnelingRequest)
this.send(knxTunnelingRequest)
this.sysLogger.error(
this.sysLogger?.error(
`KNXClient: _setTimerWaitingForACK: ${
timeoutErr.message || 'Undef error'
} no ACK received. Retransmit datagram with seqNumber ${this.getSeqNumber()} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`,
} no ACK received. Retransmit datagram with seqNumber ${
this.currentItemHandledByTheQueue
.expectedSeqNumberForACK
} from ${knxTunnelingRequest.cEMIMessage.srcAddress.toString()} to ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`,
)
this.send(
knxTunnelingRequest,
knxTunnelingRequest,
true,
this.currentItemHandledByTheQueue
.expectedSeqNumberForACK,
)
}

@@ -1247,3 +1359,3 @@ },

sProcessInboundLog += ` srcAddress: ${JSON.stringify(rinfo)}`
this.sysLogger.trace(
this.sysLogger?.trace(
`Received KNX packet: _processInboundMessage, ${sProcessInboundLog} ChannelID:${this._channelID}` ||

@@ -1315,3 +1427,3 @@ `??` +

this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: CONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1326,3 +1438,3 @@ )

) {
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: DISCONNECT_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1348,3 +1460,3 @@ )

this.sysLogger.error(
this.sysLogger?.error(
`Received KNX packet: DISCONNECT_REQUEST, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1373,3 +1485,3 @@ )

if (knxTunnelingRequest.channelID !== this._channelID) {
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: TUNNELING: L_DATA_IND, NOT FOR ME: MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1389,5 +1501,10 @@ )

)
this.send(knxTunnelAck)
this.send(
knxTunnelAck,
undefined,
false,
this.getSeqNumber(),
)
} catch (error) {
this.sysLogger.error(
this.sysLogger?.error(
`Received KNX packet: TUNNELING: L_DATA_IND, ERROR BUOLDING THE TUNNELINK ACK: ${error.message} MyChannelID:${this._channelID} ReceivedPacketChannelID: ${knxTunnelingRequest.channelID} ReceivedPacketseqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1411,3 +1528,3 @@ )

sDebugString += ` dstAddress: ${knxTunnelingRequest.cEMIMessage.dstAddress.toString()}`
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: TUNNELING: L_DATA_IND, ${sDebugString} ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1425,3 +1542,3 @@ )

) {
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: TUNNELING: L_DATA_CON, ChannelID:${this._channelID} seqCounter:${knxTunnelingRequest.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1436,3 +1553,3 @@ )

this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: TUNNELING: TUNNELING_ACK, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1443,3 +1560,6 @@ )

if (!this._options.suppress_ack_ldatareq) {
if (knxTunnelingAck.seqCounter === this.getSeqNumber()) {
if (
knxTunnelingAck.seqCounter ===
this.getCurrentItemHandledByTheQueue()
) {
this.clearTimer(KNXTimer.ACK)

@@ -1455,3 +1575,3 @@ this._numFailedTelegramACK = 0 // 25/12/2021 clear the current ACK failed telegram number

this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: TUNNELING: DELETED_TUNNELING_ACK FROM PENDING ACK's, ChannelID:${this._channelID} seqCounter:${knxTunnelingAck.seqCounter} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1462,4 +1582,4 @@ )

this.sysLogger.error(
`Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = ${knxTunnelingAck.seqCounter}`,
this.sysLogger?.error(
`Received KNX packet: TUNNELING: Unexpected Tunnel Ack with seqCounter = ${knxTunnelingAck.seqCounter}, expecting ${this.getSeqNumber()}`,
)

@@ -1486,3 +1606,3 @@ // this.emit(KNXClientEvents.error, `Unexpected Tunnel Ack ${knxTunnelingAck.seqCounter}`);

sDebugString += ` dstAddress: ${knxRoutingInd.cEMIMessage.dstAddress.toString()}`
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: ROUTING: L_DATA_IND, ${sDebugString} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1496,3 +1616,3 @@ )

) {
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: ROUTING: L_DATA_CON, Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1507,3 +1627,3 @@ )

) {
this.sysLogger.debug(
this.sysLogger?.debug(
`Received KNX packet: CONNECTIONSTATE_RESPONSE, ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}`,

@@ -1545,3 +1665,3 @@ )

} catch (e) {
this.sysLogger.error(
this.sysLogger?.error(
`Received KNX packet: Error processing inbound message: ${e.message} ${sProcessInboundLog} ChannelID:${this._channelID} Host:${this._options.ipAddr}:${this._options.ipPort}. This means that KNX-Ultimate received a malformed Header or CEMI message from your KNX Gateway.`,

@@ -1562,2 +1682,5 @@ )

),
undefined,
false,
this.getSeqNumber(),
)

@@ -1571,2 +1694,5 @@ }

),
undefined,
false,
this.getSeqNumber(),
// KNX_CONSTANTS.KNX_PORT,

@@ -1584,3 +1710,8 @@ // KNX_CONSTANTS.KNX_IP,

// }
this.send(KNXProtocol.newKNXConnectRequest(cri))
this.send(
KNXProtocol.newKNXConnectRequest(cri),
undefined,
false,
this.getSeqNumber(),
)
}

@@ -1595,3 +1726,8 @@

// }
this.send(KNXProtocol.newKNXConnectionStateRequest(channelID))
this.send(
KNXProtocol.newKNXConnectionStateRequest(channelID),
undefined,
false,
this.getSeqNumber(),
)
}

@@ -1606,3 +1742,8 @@

// }
this.send(KNXProtocol.newKNXDisconnectRequest(channelID))
this.send(
KNXProtocol.newKNXDisconnectRequest(channelID),
undefined,
false,
this.getSeqNumber(),
)
}

@@ -1614,3 +1755,8 @@

) {
this.send(KNXProtocol.newKNXDisconnectResponse(channelID, status))
this.send(
KNXProtocol.newKNXDisconnectResponse(channelID, status),
undefined,
false,
this.getSeqNumber(),
)
}

@@ -1626,4 +1772,9 @@

)
this.send(KNXProtocol.newKNXSecureSessionRequest(cri, oHPAI))
this.send(
KNXProtocol.newKNXSecureSessionRequest(cri, oHPAI),
undefined,
false,
this.getSeqNumber(),
)
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc