mirror of
https://github.com/jwetzell/acn-js.git
synced 2026-07-26 10:28:41 +00:00
start work towards DMP protocol decoding
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# acn-js
|
||||
not sure how far I will take this but messing around with E1.17 ACN protocol
|
||||
|
||||
## areas
|
||||
## packet decoding
|
||||
- rlp
|
||||
- sdt
|
||||
- vectors
|
||||
@@ -23,4 +23,16 @@ not sure how far I will take this but messing around with E1.17 ACN protocol
|
||||
- [x] DISCONNECT
|
||||
- [x] DISCONNECTING
|
||||
- dmp
|
||||
- vectors
|
||||
- [ ] GET_PROPERTY
|
||||
- [ ] SET_PROPERTY
|
||||
- [ ] GET_PROPERTY_REPLY
|
||||
- [ ] EVENT
|
||||
- [ ] SUBSCRIBE
|
||||
- [ ] UNSUBSCRIBE
|
||||
- [ ] GET_PROPERTY_FAIL
|
||||
- [ ] SET_PROPERTY_FAIL
|
||||
- [ ] SUBSCRIBE_ACCEPT
|
||||
- [ ] SUBSCRIBE_REJECT
|
||||
- [ ] SYNC_EVENT
|
||||
- ddl
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export enum Protocol {
|
||||
SDT = 1,
|
||||
DMP,
|
||||
}
|
||||
|
||||
export enum SDTVector {
|
||||
@@ -22,6 +23,26 @@ export enum SDTVector {
|
||||
SESSIONS,
|
||||
}
|
||||
|
||||
export enum DMPVector {
|
||||
GET_PROPERTY = 1,
|
||||
SET_PROPERTY,
|
||||
GET_PROPERTY_REPLY,
|
||||
EVENT,
|
||||
RESERVED_1,
|
||||
RESERVED_2,
|
||||
SUBSCRIBE,
|
||||
UNSUBSCRIBE,
|
||||
GET_PROPERTY_FAIL,
|
||||
SET_PROPERTY_FAIL,
|
||||
RESERVED_3,
|
||||
SUBSCRIBE_ACCEPT,
|
||||
SUBSCRIBE_REJECT,
|
||||
RESERVED_4,
|
||||
RESERVED_5,
|
||||
RESERVED_6,
|
||||
SYNC_EVENT,
|
||||
}
|
||||
|
||||
export enum TransportLayerAddressType {
|
||||
SDT_ADDR_NULL = 0,
|
||||
SDT_ADDR_IPV4,
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { DMPVector } from '../enums';
|
||||
import { DeviceManagementProtocolPDU, DMPAddressDataType, DMPGetPropertyData } from '../types';
|
||||
|
||||
export function decode(bytes: Uint8Array): DeviceManagementProtocolPDU {
|
||||
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;
|
||||
const headerFlag = ((flags >> 1) & 0x1) === 1;
|
||||
|
||||
if (!vectorFlag) {
|
||||
throw new Error('SDT PDU must have a vector');
|
||||
}
|
||||
|
||||
const dataFlag = (flags & 0x1) === 1;
|
||||
|
||||
if (!dataFlag) {
|
||||
// TODO(jwetzell): idk if this is true
|
||||
throw new Error('SDT 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.getUint8(vectorOffset);
|
||||
|
||||
let headerOffset = (vectorOffset += 1);
|
||||
|
||||
const addressAndDataTypes = view.getUint8(headerOffset);
|
||||
const addressType = (addressAndDataTypes >> 6) & 0x1;
|
||||
const dataType = (addressAndDataTypes >> 4) & 0x3;
|
||||
const elementSize = addressAndDataTypes & 0x11;
|
||||
|
||||
const addressAndDataType = {
|
||||
addressType,
|
||||
dataType,
|
||||
elementSize
|
||||
}
|
||||
|
||||
const dataOffset = headerOffset + 1;
|
||||
// NOTE(jwetzell): flags/lengthH + lengthL + lengthX + vector + header
|
||||
const dataLength = length - (1 + 1 + (lengthFlag ? 1 : 0) + 1 + 1);
|
||||
const data = decodeData(vector, bytes.subarray(dataOffset, dataOffset + dataLength), addressAndDataType);
|
||||
console.log('decoded Data', data)
|
||||
return {
|
||||
vector,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
function decodeData(vector: number, bytes: Uint8Array, addressAndDataType: DMPAddressDataType): DMPGetPropertyData | Uint8Array {
|
||||
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
||||
console.log('pdu bytes', bytes)
|
||||
console.log('pdu address data type', addressAndDataType)
|
||||
switch (vector) {
|
||||
default:
|
||||
console.error(`unhandled DMP vector: ${vector}`);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
decode,
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import rlp from './rlp';
|
||||
import sdt from './sdt';
|
||||
import dmp from './dmp';
|
||||
export default {
|
||||
rlp,
|
||||
sdt,
|
||||
dmp,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import pdu from '.';
|
||||
import { Protocol, SDTVector } from '../enums';
|
||||
import {
|
||||
DeviceManagementProtocolPDU,
|
||||
SDTAckData,
|
||||
SDTConnectAcceptData,
|
||||
SDTConnectData,
|
||||
@@ -113,10 +115,12 @@ function decodeClientBlock(bytes: Uint8Array) {
|
||||
const dataOffset = headerOffset + 6;
|
||||
// NOTE(jwetzell): flags/lengthH + lengthL + lengthX + vector + header
|
||||
const dataLength = length - (1 + 1 + (lengthFlag ? 1 : 0) + 2 + 6);
|
||||
let data: SessionDataTransportPDU | Uint8Array = bytes.subarray(dataOffset, dataOffset + dataLength);
|
||||
let data: SessionDataTransportPDU | DeviceManagementProtocolPDU | Uint8Array = bytes.subarray(dataOffset, dataOffset + dataLength);
|
||||
|
||||
if (clientProtocol === Protocol.SDT) {
|
||||
data = decode(data);
|
||||
} else if (clientProtocol === Protocol.DMP) {
|
||||
data = pdu.dmp.decode(data)
|
||||
} else {
|
||||
console.error(`SDT client block contains unknown protocol: ${clientProtocol}`);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TransportLayerAddressType, SDTVector, SDTReasonCode } from './enums';
|
||||
import { TransportLayerAddressType, SDTVector, SDTReasonCode, DMPVector } from './enums';
|
||||
|
||||
export type UDPPreamble = {
|
||||
preambleSize: number;
|
||||
@@ -133,9 +133,26 @@ export type SessionDataTransportPDU = {
|
||||
| Uint8Array;
|
||||
};
|
||||
|
||||
export type DMPAddressDataType = {
|
||||
addressType: number;
|
||||
dataType: number;
|
||||
elementSize: number;
|
||||
};
|
||||
|
||||
export type DMPGetPropertyData = {
|
||||
address: number
|
||||
}
|
||||
|
||||
export type DMPSubscribePropertyData = DMPGetPropertyData
|
||||
|
||||
export type DeviceManagementProtocolPDU = {
|
||||
vector: DMPVector;
|
||||
data: DMPGetPropertyData | DMPSubscribePropertyData | Uint8Array;
|
||||
};
|
||||
|
||||
export type SDTClientBlock = {
|
||||
memberID: number;
|
||||
clientProtocol: number;
|
||||
association: number;
|
||||
data: SessionDataTransportPDU | Uint8Array;
|
||||
data: SessionDataTransportPDU | DeviceManagementProtocolPDU | Uint8Array;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user