knxnetjs
Version:
A TypeScript library for KNXnet/IP communication
161 lines • 5.93 kB
JavaScript
;
/**
* KNX USB Transfer Protocol implementation
* Handles the KNX USB Transfer Protocol Header and Body structures
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.KNXUSBTransferFrame = exports.KNXUSBTransferEMIId = exports.KNXUSBTransferProtocolId = void 0;
var KNXUSBTransferProtocolId;
(function (KNXUSBTransferProtocolId) {
KNXUSBTransferProtocolId[KNXUSBTransferProtocolId["KNXTunnel"] = 1] = "KNXTunnel";
KNXUSBTransferProtocolId[KNXUSBTransferProtocolId["BusAccessServerFeatureService"] = 15] = "BusAccessServerFeatureService";
})(KNXUSBTransferProtocolId || (exports.KNXUSBTransferProtocolId = KNXUSBTransferProtocolId = {}));
var KNXUSBTransferEMIId;
(function (KNXUSBTransferEMIId) {
KNXUSBTransferEMIId[KNXUSBTransferEMIId["EMI1"] = 1] = "EMI1";
KNXUSBTransferEMIId[KNXUSBTransferEMIId["EMI2"] = 2] = "EMI2";
KNXUSBTransferEMIId[KNXUSBTransferEMIId["cEMI"] = 3] = "cEMI";
})(KNXUSBTransferEMIId || (exports.KNXUSBTransferEMIId = KNXUSBTransferEMIId = {}));
class KNXUSBTransferFrame {
constructor(header, body) {
this.header = header;
this.body = body;
}
/**
* Creates a KNX USB Transfer Frame from a Buffer
*/
static fromBuffer(buffer) {
if (buffer.length < 8) {
throw new Error("Buffer too short for KNX USB Transfer Header");
}
// Parse Header
const header = {
protocolVersion: buffer[0] || 0,
headerLength: buffer[1] || 0,
bodyLength: buffer.readUInt16BE(2),
protocolId: buffer[4] || 0,
emiId: buffer[5] || 0,
manufacturerCode: buffer.readUInt16BE(6),
};
// Validate header
if (header.headerLength !== 0x08) {
throw new Error(`Invalid header length: ${header.headerLength}`);
}
if (buffer.length < header.headerLength + 1) {
throw new Error("Buffer too short for KNX USB Transfer Body");
}
// Parse Body
const bodyStart = header.headerLength;
const emiMessageCode = buffer[bodyStart] || 0;
const data = buffer.subarray(bodyStart + 1);
const body = {
emiMessageCode,
data,
};
return new KNXUSBTransferFrame(header, body);
}
/**
* Converts the frame to a Buffer
*/
toBuffer() {
const bodyBuffer = Buffer.allocUnsafe(1 + this.body.data.length);
bodyBuffer[0] = this.body.emiMessageCode;
this.body.data.copy(bodyBuffer, 1);
const headerBuffer = Buffer.allocUnsafe(8);
headerBuffer[0] = this.header.protocolVersion;
headerBuffer[1] = this.header.headerLength;
headerBuffer.writeUInt16BE(bodyBuffer.length, 2); // body length
headerBuffer[4] = this.header.protocolId;
headerBuffer[5] = this.header.emiId;
headerBuffer.writeUInt16BE(this.header.manufacturerCode, 6);
return Buffer.concat([headerBuffer, bodyBuffer]);
}
/**
* Creates a KNX USB Transfer Frame for cEMI data
*/
static createForCEMI(cemiData, manufacturerCode = 0x0000) {
const body = {
emiMessageCode: cemiData[0],
data: cemiData.subarray(1),
};
const header = {
protocolVersion: 0x00,
headerLength: 0x08,
bodyLength: 1 + cemiData.length, // message code + data
protocolId: KNXUSBTransferProtocolId.KNXTunnel,
emiId: KNXUSBTransferEMIId.cEMI,
manufacturerCode,
};
return new KNXUSBTransferFrame(header, body);
}
/**
* Creates a KNX USB Transfer Frame for bus access
*/
static createForBusAccess(service, feature, value) {
const body = {
emiMessageCode: feature,
data: value,
};
const header = {
protocolVersion: 0x00,
headerLength: 0x08,
bodyLength: 1 + value.length, // feature + data
protocolId: KNXUSBTransferProtocolId.BusAccessServerFeatureService,
emiId: service,
manufacturerCode: 0x0000,
};
return new KNXUSBTransferFrame(header, body);
}
/**
* Validates if a buffer contains a valid KNX USB Transfer Frame
*/
static isValid(buffer) {
if (buffer.length < 9) {
// Minimum: 8-byte header + 1-byte EMI message code
return false;
}
const protocolVersion = buffer[0];
const headerLength = buffer[1];
const protocolId = buffer[4];
const emiId = buffer[5];
return (protocolVersion === 0x00 &&
headerLength === 0x08 &&
protocolId === KNXUSBTransferProtocolId.KNXTunnel &&
emiId === KNXUSBTransferEMIId.cEMI);
}
/**
* Gets the cEMI data from the frame body
*/
getCEMIData() {
if (this.body.emiMessageCode === 0x11) {
// cEMI format
return this.body.data;
}
return null;
}
/**
* Returns frame information as a string for debugging
*/
toString() {
return `KNXUSBTransferFrame {
header: {
protocolVersion: 0x${this.header.protocolVersion
.toString(16)
.padStart(2, "0")},
headerLength: 0x${this.header.headerLength.toString(16).padStart(2, "0")},
bodyLength: ${this.header.bodyLength},
protocolId: 0x${this.header.protocolId.toString(16).padStart(2, "0")},
emiId: 0x${this.header.emiId.toString(16).padStart(2, "0")},
manufacturerCode: 0x${this.header.manufacturerCode
.toString(16)
.padStart(4, "0")}
},
body: {
emiMessageCode: 0x${this.body.emiMessageCode.toString(16).padStart(2, "0")},
dataLength: ${this.body.data.length}
}
}`;
}
}
exports.KNXUSBTransferFrame = KNXUSBTransferFrame;
//# sourceMappingURL=knx-usb-transfer.js.map