mirror of
https://github.com/jwetzell/acn-js.git
synced 2026-09-05 13:38:58 +00:00
initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
export * from './models';
|
||||
export * from './udp';
|
||||
@@ -0,0 +1,21 @@
|
||||
export type Protocols = {
|
||||
SDT: 1;
|
||||
};
|
||||
|
||||
export type UDPPreamble = {
|
||||
preambleSize: number;
|
||||
postambleSize: number;
|
||||
packetIdentifier: string;
|
||||
};
|
||||
|
||||
export type ACNPacket<PreambleType, PDUBlockType, PostambleType> = {
|
||||
preamble: PreambleType;
|
||||
pduBlock: PDUBlockType;
|
||||
postamble: PostambleType;
|
||||
};
|
||||
|
||||
export type RootLayerPDU = {
|
||||
vector: number;
|
||||
header: Uint8Array;
|
||||
data: Uint8Array;
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
import rlp from './rlp';
|
||||
export default {
|
||||
rlp,
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import { RootLayerPDU } from '../models';
|
||||
|
||||
function decode(bytes: Uint8Array): RootLayerPDU {
|
||||
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
||||
const flags = view.getUint8(0) >> 4;
|
||||
const lengthFlag = ((flags >> 3) & 0x1) === 1;
|
||||
const vectorFlag = ((flags >> 2) & 0x1) === 1;
|
||||
|
||||
if (!vectorFlag) {
|
||||
throw new Error('Root Layer PDU must have a vector');
|
||||
}
|
||||
|
||||
const headerFlag = ((flags >> 1) & 0x1) === 1;
|
||||
|
||||
if (!headerFlag) {
|
||||
throw new Error('Root Layer PDU must have a header');
|
||||
}
|
||||
|
||||
const dataFlag = (flags & 0x1) === 1;
|
||||
|
||||
if (!dataFlag) {
|
||||
// TODO(jwetzell): idk know if this is true
|
||||
throw new Error('Root Layer PDU must have data');
|
||||
}
|
||||
|
||||
const lengthH = view.getUint8(0) & 0x0f;
|
||||
let lengthOffset = 1;
|
||||
const lengthL = view.getUint8(lengthOffset);
|
||||
|
||||
let length = (lengthH << 8) + lengthL;
|
||||
|
||||
if (lengthFlag) {
|
||||
lengthOffset += 1;
|
||||
const lengthX = view.getUint8(lengthOffset);
|
||||
length = (lengthH << 16) + (lengthL << 8) + lengthX;
|
||||
}
|
||||
let vectorOffset = lengthOffset + 1;
|
||||
|
||||
if (lengthFlag) {
|
||||
vectorOffset += 1;
|
||||
}
|
||||
|
||||
const vector = view.getUint32(vectorOffset);
|
||||
const headerOffset = vectorOffset + 4;
|
||||
|
||||
const header = bytes.subarray(headerOffset, headerOffset + 16);
|
||||
const dataOffset = headerOffset + 16;
|
||||
// NOTE(jwetzell): flags/lengthH + lengthL + lengthX + vector + header
|
||||
const dataLength = length - (1 + 1 + (lengthFlag ? 1 : 0) + 4 + 16);
|
||||
const data = bytes.subarray(dataOffset, dataOffset + dataLength);
|
||||
|
||||
return {
|
||||
vector,
|
||||
header,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
decode,
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ACNPacket, RootLayerPDU, UDPPreamble } from './models';
|
||||
import pdu from './pdu';
|
||||
|
||||
// ANSI E1.17 - 2015 (R2020) EPI 17
|
||||
export function decode(bytes: Uint8Array): ACNPacket<UDPPreamble, RootLayerPDU, undefined> {
|
||||
if (bytes.byteLength < 16) {
|
||||
throw new Error('ACN UDP packet must be at least 16 bytes long');
|
||||
}
|
||||
|
||||
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
||||
|
||||
const preambleSize = view.getUint16(0, false);
|
||||
if (preambleSize != 16) {
|
||||
throw new Error('ACN UDP preamble size should 16');
|
||||
}
|
||||
const postambleSize = view.getUint16(2, false);
|
||||
if (postambleSize > 0) {
|
||||
throw new Error('ACN UDP postamble size should be 0');
|
||||
}
|
||||
|
||||
const packetIdentifier = new TextDecoder().decode(bytes.subarray(4, preambleSize));
|
||||
|
||||
if (packetIdentifier !== 'ASC-E1.17\0\0\0') {
|
||||
throw new Error('ACN Packet Identifier is incorrect');
|
||||
}
|
||||
|
||||
const pduBlock = pdu.rlp.decode(bytes.subarray(preambleSize));
|
||||
|
||||
return {
|
||||
preamble: {
|
||||
preambleSize,
|
||||
postambleSize,
|
||||
packetIdentifier,
|
||||
},
|
||||
pduBlock,
|
||||
postamble: undefined,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user