forked from BiancoRoyal/node-bacstack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnpdu.js
More file actions
117 lines (105 loc) · 3.47 KB
/
Copy pathnpdu.js
File metadata and controls
117 lines (105 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
'use strict';
const baEnum = require('./enum');
const DEFAULT_HOP_COUNT = 0xFF;
const BACNET_PROTOCOL_VERSION = 1;
const BacnetAddressTypes = {
NONE: 0,
IP: 1
};
const decodeTarget = (buffer, offset) => {
let len = 0;
const target = {type: BacnetAddressTypes.NONE, net: (buffer[offset + len++] << 8) | (buffer[offset + len++] << 0)};
const adrLen = buffer[offset + len++];
if (adrLen > 0) {
target.adr = [];
for (let i = 0; i < adrLen; i++) {
target.adr.push(buffer[offset + len++]);
}
}
return {
target: target,
len: len
};
};
const encodeTarget = (buffer, target) => {
buffer.buffer[buffer.offset++] = (target.net & 0xFF00) >> 8;
buffer.buffer[buffer.offset++] = (target.net & 0x00FF) >> 0;
if (target.net === 0xFFFF || !target.adr) {
buffer.buffer[buffer.offset++] = 0;
} else {
buffer.buffer[buffer.offset++] = target.adr.length;
if (target.adr.length > 0) {
for (let i = 0; i < target.adr.length; i++) {
buffer.buffer[buffer.offset++] = target.adr[i];
}
}
}
};
module.exports.decodeFunction = (buffer, offset) => {
if (buffer[offset + 0] !== BACNET_PROTOCOL_VERSION) return;
return buffer[offset + 1];
};
module.exports.decode = (buffer, offset) => {
let adrLen;
const orgOffset = offset;
offset++;
const funct = buffer[offset++];
let destination;
if (funct & baEnum.NpduControlBits.DESTINATION_SPECIFIED) {
const tmpDestination = decodeTarget(buffer, offset);
offset += tmpDestination.len;
destination = tmpDestination.target;
}
let source;
if (funct & baEnum.NpduControlBits.SOURCE_SPECIFIED) {
const tmpSource = decodeTarget(buffer, offset);
offset += tmpSource.len;
source = tmpSource.target;
}
let hopCount = 0;
if (funct & baEnum.NpduControlBits.DESTINATION_SPECIFIED) {
hopCount = buffer[offset++];
}
let networkMsgType = baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK;
let vendorId = 0;
if (funct & baEnum.NpduControlBits.NETWORK_LAYER_MESSAGE) {
networkMsgType = buffer[offset++];
if (networkMsgType >= 0x80) {
vendorId = (buffer[offset++] << 8) | (buffer[offset++] << 0);
} else if (networkMsgType === baEnum.NetworkLayerMessageType.WHO_IS_ROUTER_TO_NETWORK) {
offset += 2;
}
}
if (buffer[orgOffset + 0] !== BACNET_PROTOCOL_VERSION) return;
return {
len: offset - orgOffset,
funct: funct,
destination: destination,
source: source,
hopCount: hopCount,
networkMsgType: networkMsgType,
vendorId: vendorId
};
};
module.exports.encode = (buffer, funct, destination, source, hopCount, networkMsgType, vendorId) => {
const hasDestination = destination && destination.net > 0;
const hasSource = source && source.net > 0 && source.net !== 0xFFFF;
buffer.buffer[buffer.offset++] = BACNET_PROTOCOL_VERSION;
buffer.buffer[buffer.offset++] = funct | (hasDestination ? baEnum.NpduControlBits.DESTINATION_SPECIFIED : 0) | (hasSource ? baEnum.NpduControlBits.SOURCE_SPECIFIED : 0);
if (hasDestination) {
encodeTarget(buffer, destination);
}
if (hasSource) {
encodeTarget(buffer, source);
}
if (hasDestination) {
buffer.buffer[buffer.offset++] = hopCount || DEFAULT_HOP_COUNT;
}
if ((funct & baEnum.NpduControlBits.NETWORK_LAYER_MESSAGE) > 0) {
buffer.buffer[buffer.offset++] = networkMsgType;
if (networkMsgType >= 0x80) {
buffer.buffer[buffer.offset++] = (vendorId & 0xFF00) >> 8;
buffer.buffer[buffer.offset++] = (vendorId & 0x00FF) >> 0;
}
}
};