mirror of
https://github.com/jwetzell/psn-js.git
synced 2026-07-26 10:38:50 +00:00
remove binary-parsser lib dependency
This commit is contained in:
@@ -14,5 +14,6 @@ module.exports = {
|
||||
'class-methods-use-this': 'off',
|
||||
'import/extensions': 'off',
|
||||
'import/no-relative-packages': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -13,15 +13,18 @@ js implementation of the [PosiStageNet protocol](https://github.com/vyv/psn-cpp/
|
||||
const { Decoder } = require('@jwetzell/posistagenet')
|
||||
const decoder = new Decoder()
|
||||
|
||||
const buffer = Buffer.from('source PSN packets from somewhere')
|
||||
const infoPacketBuffer = Buffer.from('5667348000000c0001000000000000000203010101000b00536572766572204e616d650200118001000d8000000900547261636b65722031','hex')
|
||||
const dataPacketBuffer = Buffer.from('5567288000000c00010000000000000002030101010014800100108000000c000000803f0000803f0000803f','hex')
|
||||
|
||||
decoder.decode(buffer)
|
||||
decoder.decode(infoPacketBuffer)
|
||||
decoder.decode(dataPacketBuffer)
|
||||
|
||||
// data from PSN Info packets
|
||||
console.log(decoder.info)
|
||||
// the system_name from info packets if available
|
||||
console.log(decoder.system_name)
|
||||
|
||||
// data from PSN Data packets
|
||||
console.log(decoder.data)
|
||||
// map of trackers populated with any data that has been received
|
||||
// this merges both info and data packet properties into one
|
||||
console.log(decoder.trackers)
|
||||
|
||||
```
|
||||
|
||||
@@ -56,3 +59,6 @@ infoPackets.forEach((infoPacket)=>{
|
||||
|
||||
```
|
||||
|
||||
## Notes
|
||||
- UInt64
|
||||
- PosiStageNet uses 64 bit UInt's for timestamp values make sure to use [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) if using values over `Number.MAX_SAFE_INTEGER`
|
||||
+14
-11
@@ -1,3 +1,4 @@
|
||||
// recreation of psn_client.cpp example from https://github.com/vyv/psn-cpp
|
||||
const dgram = require('dgram');
|
||||
const { Decoder } = require('..');
|
||||
|
||||
@@ -14,29 +15,29 @@ client.on('message', (buffer) => {
|
||||
client.bind(56565, '0.0.0.0');
|
||||
|
||||
setInterval(() => {
|
||||
if (decoder.info.system_name) {
|
||||
console.log(`System Name: ${decoder.info.system_name}`);
|
||||
if (decoder.system_name) {
|
||||
console.log(`System Name: ${decoder.system_name}`);
|
||||
}
|
||||
if (Object.keys(decoder.info.trackers).length > 0) {
|
||||
console.log(`Tracker Count: ${Object.keys(decoder.info.trackers).length}`);
|
||||
if (Object.keys(decoder.trackers).length > 0) {
|
||||
console.log(`Tracker Count: ${Object.keys(decoder.trackers).length}`);
|
||||
}
|
||||
|
||||
Object.entries(decoder.data.trackers).forEach(([trackerId, tracker]) => {
|
||||
Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => {
|
||||
console.log(
|
||||
`Tracker - id: ${trackerId} | name: ${
|
||||
decoder.info.trackers[trackerId]?.name ? decoder.info.trackers[trackerId]?.name : ''
|
||||
decoder.trackers[trackerId]?.tracker_name ? decoder.trackers[trackerId]?.tracker_name : ''
|
||||
}`
|
||||
);
|
||||
if (tracker.pos) {
|
||||
console.log(`\tpos: ${tracker.pos.x}, ${tracker.pos.y}, ${tracker.pos.z}`);
|
||||
console.log(`\tpos: ${tracker.pos.pos_x}, ${tracker.pos.pos_y}, ${tracker.pos.pos_z}`);
|
||||
}
|
||||
|
||||
if (tracker.speed) {
|
||||
console.log(`\tspeed: ${tracker.speed.x}, ${tracker.speed.y}, ${tracker.speed.z}`);
|
||||
console.log(`\tspeed: ${tracker.speed.speed_x}, ${tracker.speed.speed_y}, ${tracker.speed.speed_z}`);
|
||||
}
|
||||
|
||||
if (tracker.ori) {
|
||||
console.log(`\tori: ${tracker.ori.x}, ${tracker.ori.y}, ${tracker.ori.z}`);
|
||||
console.log(`\tori: ${tracker.ori.ori_x}, ${tracker.ori.ori_y}, ${tracker.ori.ori_z}`);
|
||||
}
|
||||
|
||||
if (tracker.status) {
|
||||
@@ -44,11 +45,13 @@ setInterval(() => {
|
||||
}
|
||||
|
||||
if (tracker.accel) {
|
||||
console.log(`\taccel: ${tracker.accel.x}, ${tracker.accel.y}, ${tracker.accel.z}`);
|
||||
console.log(`\taccel: ${tracker.accel.accel_x}, ${tracker.accel.accel_y}, ${tracker.accel.accel_z}`);
|
||||
}
|
||||
|
||||
if (tracker.trgtpos) {
|
||||
console.log(`\ttrgtpos: ${tracker.trgtpos.x}, ${tracker.trgtpos.y}, ${tracker.trgtpos.z}`);
|
||||
console.log(
|
||||
`\ttrgtpos: ${tracker.trgtpos.trgtpos_x}, ${tracker.trgtpos.trgtpos_y}, ${tracker.trgtpos.trgtpos_z}`
|
||||
);
|
||||
}
|
||||
|
||||
if (tracker.timestamp) {
|
||||
|
||||
+18
-8
@@ -1,8 +1,10 @@
|
||||
// recreation of psn_server.cpp example from https://github.com/vyv/psn-cpp
|
||||
const dgram = require('dgram');
|
||||
const { Encoder, Tracker } = require('..');
|
||||
const { Encoder, Tracker, Decoder } = require('..');
|
||||
|
||||
const client = dgram.createSocket('udp4');
|
||||
const encoder = new Encoder('Test PSN Server', 2, 0);
|
||||
const decoder = new Decoder();
|
||||
|
||||
const trackers = [];
|
||||
|
||||
@@ -22,7 +24,7 @@ const distFromSun = [0, 0.58, 1.08, 1.5, 2.28, 7.78, 14.29, 28.71, 45.04, 59.13]
|
||||
|
||||
let timestamp = 0;
|
||||
setInterval(() => {
|
||||
for (let index = 0; index < trackers.length; index += 1) {
|
||||
orbits.forEach((orbit, index) => {
|
||||
const a = 1.0 / orbits[index];
|
||||
const b = distFromSun[index];
|
||||
const x = timestamp;
|
||||
@@ -36,19 +38,27 @@ setInterval(() => {
|
||||
trackers[index].setTrgtPos(3, 14, 16);
|
||||
trackers[index].setStatus(index / 10.0);
|
||||
trackers[index].setTimestamp(timestamp);
|
||||
}
|
||||
});
|
||||
|
||||
const dataPackets = encoder.getDataPackets(timestamp, trackers);
|
||||
|
||||
dataPackets.forEach((packet) => {
|
||||
dataPackets.forEach((packet, index) => {
|
||||
const decodedPacket = decoder.decode(packet);
|
||||
console.log(
|
||||
`Sending PSN_DATA_PACKET : Frame Id = ${decodedPacket.packet_header.frame_id} , Packet Count = ${index + 1}`
|
||||
);
|
||||
client.send(packet, 56565, '236.10.10.10');
|
||||
});
|
||||
timestamp += 1;
|
||||
}, 20);
|
||||
}, 5);
|
||||
|
||||
setInterval(() => {
|
||||
const infoPackets = encoder.getInfoPackets(timestamp, trackers);
|
||||
infoPackets.forEach((packet) => {
|
||||
infoPackets.forEach((packet, index) => {
|
||||
const decodedPacket = decoder.decode(packet);
|
||||
console.log(
|
||||
`Sending PSN_INFO_PACKET : Frame Id = ${decodedPacket.packet_header.frame_id} , Packet Count = ${index + 1}`
|
||||
);
|
||||
|
||||
client.send(packet, 56565, '236.10.10.10');
|
||||
});
|
||||
}, 1000);
|
||||
}, 500);
|
||||
|
||||
Generated
-11
@@ -8,9 +8,6 @@
|
||||
"name": "@jwetzell/posistagenet",
|
||||
"version": "0.2.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"binary-parser": "^2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.48.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
@@ -429,14 +426,6 @@
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/binary-parser": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/binary-parser/-/binary-parser-2.2.1.tgz",
|
||||
"integrity": "sha512-5ATpz/uPDgq5GgEDxTB4ouXCde7q2lqAQlSdBRQVl/AJnxmQmhIfyxJx+0MGu//D5rHQifkfGbWWlaysG0o9NA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
||||
+1
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@jwetzell/posistagenet",
|
||||
"version": "0.2.1",
|
||||
"version": "0.3.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -19,8 +19,5 @@
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"prettier": "^3.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"binary-parser": "^2.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
PACKET_HEADER_SIZE: 16,
|
||||
MAX_UDP_PACKET_SIZE: 1500,
|
||||
CHUNK_HEADER_SIZE: 4,
|
||||
};
|
||||
+49
-71
@@ -1,8 +1,7 @@
|
||||
const PacketParser = require('./decoders/packet');
|
||||
const InfoPacket = require('./models/packets/info-packet');
|
||||
const DataPacket = require('./models/packets/data-packet');
|
||||
const packetDecoder = require('./decoders/packet');
|
||||
|
||||
class Decoder {
|
||||
// TODO(jwetzell): check if these last packet headers are necessary to hold on to
|
||||
lastInfoPacketHeader;
|
||||
|
||||
lastDataPacketHeader;
|
||||
@@ -12,74 +11,58 @@ class Decoder {
|
||||
dataPacketFrames = {};
|
||||
|
||||
constructor() {
|
||||
this.info = {
|
||||
trackers: {},
|
||||
};
|
||||
this.system_name = '';
|
||||
|
||||
this.data = {
|
||||
trackers: {},
|
||||
};
|
||||
this.trackers = {};
|
||||
}
|
||||
|
||||
updateInfo(framePackets) {
|
||||
framePackets.forEach((packet) => {
|
||||
packet.subChunks?.forEach((subChunk) => {
|
||||
if (subChunk.id === 0x0001) {
|
||||
// NOTE(jwetzell): system name subChunk
|
||||
this.info.system_name = subChunk.system_name;
|
||||
} else if (subChunk.id === 0x0002) {
|
||||
subChunk.trackers?.forEach((tracker) => {
|
||||
if (this.info.trackers[tracker.id] === undefined) {
|
||||
this.info.trackers[tracker.id] = {};
|
||||
}
|
||||
this.info.trackers[tracker.id].name = tracker.tracker_name.tracker_name;
|
||||
});
|
||||
}
|
||||
});
|
||||
if (packet.system_name) {
|
||||
this.system_name = packet.system_name.system_name;
|
||||
}
|
||||
|
||||
if (packet.tracker_list?.trackers) {
|
||||
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
|
||||
this.trackers[trackerId] = {
|
||||
...this.trackers[trackerId],
|
||||
...tracker.tracker_name,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateData(framePackets) {
|
||||
framePackets.forEach((packet) => {
|
||||
packet.subChunks?.forEach((subChunk) => {
|
||||
if (subChunk.id === 0x0001) {
|
||||
subChunk.trackers?.forEach((tracker) => {
|
||||
if (this.data.trackers[tracker.id] === undefined) {
|
||||
this.data.trackers[tracker.id] = {};
|
||||
}
|
||||
this.data.trackers[tracker.id] = {
|
||||
pos: tracker.pos,
|
||||
speed: tracker.speed,
|
||||
ori: tracker.ori,
|
||||
status: tracker.status,
|
||||
accel: tracker.accel,
|
||||
trgtpos: tracker.trgtpos,
|
||||
timestamp: tracker.timestamp,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
if (packet.tracker_list) {
|
||||
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
|
||||
this.trackers[trackerId] = {
|
||||
...this.trackers[trackerId],
|
||||
...tracker,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete
|
||||
decode(packetBuf) {
|
||||
const packet = PacketParser.parse(packetBuf);
|
||||
|
||||
const packet = packetDecoder(packetBuf);
|
||||
if (packet.id === 0x6756) {
|
||||
const infoPacket = new InfoPacket(packet);
|
||||
const infoPacket = packet;
|
||||
if (infoPacket) {
|
||||
if (infoPacket.subChunks?.length > 0) {
|
||||
const currentInfoPacketHeader = infoPacket.getHeaderPacket();
|
||||
if (infoPacket.has_subchunks > 0) {
|
||||
const currentInfoPacketHeader = infoPacket.packet_header;
|
||||
if (!currentInfoPacketHeader) {
|
||||
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
|
||||
return;
|
||||
throw new Error('malformed packet');
|
||||
}
|
||||
|
||||
const systemSubChunk = infoPacket.getSystemPacket();
|
||||
const systemSubChunk = infoPacket.system_name;
|
||||
if (!systemSubChunk) {
|
||||
// NOTE(jwetzell): not sure that info packets without a system subchunk are valid?
|
||||
return;
|
||||
throw new Error('malformed packet');
|
||||
}
|
||||
|
||||
if (this.infoPacketFrames[currentInfoPacketHeader.frame_id] === undefined) {
|
||||
@@ -99,32 +82,27 @@ class Decoder {
|
||||
}
|
||||
}
|
||||
} else if (packet.id === 0x6755) {
|
||||
const dataPacket = new DataPacket(packet);
|
||||
if (dataPacket) {
|
||||
if (dataPacket.subChunks?.length > 0) {
|
||||
const currentDataPacketHeader = dataPacket.getHeaderPacket();
|
||||
if (!currentDataPacketHeader) {
|
||||
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dataPacketFrames[currentDataPacketHeader.frame_id] === undefined) {
|
||||
this.dataPacketFrames[currentDataPacketHeader.frame_id] = [];
|
||||
}
|
||||
this.dataPacketFrames[currentDataPacketHeader.frame_id].push(dataPacket);
|
||||
|
||||
if (
|
||||
this.dataPacketFrames[currentDataPacketHeader.frame_id].length ===
|
||||
currentDataPacketHeader.frame_packet_count
|
||||
) {
|
||||
this.updateData(this.dataPacketFrames[currentDataPacketHeader.frame_id]);
|
||||
delete this.dataPacketFrames[currentDataPacketHeader.frame_id];
|
||||
}
|
||||
|
||||
this.lastDataPacketHeader = currentDataPacketHeader;
|
||||
const dataPacket = packet;
|
||||
if (dataPacket.has_subchunks) {
|
||||
const currentDataPacketHeader = dataPacket.packet_header;
|
||||
if (!currentDataPacketHeader) {
|
||||
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
|
||||
throw new Error('malformed packet');
|
||||
}
|
||||
if (this.dataPacketFrames[currentDataPacketHeader.frame_id] === undefined) {
|
||||
this.dataPacketFrames[currentDataPacketHeader.frame_id] = [];
|
||||
}
|
||||
this.dataPacketFrames[currentDataPacketHeader.frame_id].push(dataPacket);
|
||||
if (
|
||||
this.dataPacketFrames[currentDataPacketHeader.frame_id].length === currentDataPacketHeader.frame_packet_count
|
||||
) {
|
||||
this.updateData(this.dataPacketFrames[currentDataPacketHeader.frame_id]);
|
||||
delete this.dataPacketFrames[currentDataPacketHeader.frame_id];
|
||||
}
|
||||
this.lastDataPacketHeader = currentDataPacketHeader;
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-19
@@ -1,20 +1,16 @@
|
||||
const { Parser } = require('binary-parser');
|
||||
module.exports = (buffer, dataDecoder) => {
|
||||
let offset = 0;
|
||||
const chunk = {};
|
||||
chunk.id = buffer.readUInt16LE(offset);
|
||||
offset += 2;
|
||||
|
||||
module.exports = new Parser()
|
||||
.uint16le('id')
|
||||
.uint16le('data_len', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return Number.parseInt(binary.substring(1), 2);
|
||||
},
|
||||
})
|
||||
.seek(-2)
|
||||
.uint16le('has_subchunks', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return binary.charAt(0) === '1';
|
||||
},
|
||||
})
|
||||
.buffer('chunk_data', {
|
||||
length: 'data_len',
|
||||
});
|
||||
// NOTE(jwetzell): this data is split up as 1 bit for has_subchunks and 15 bits for the data_len
|
||||
const combinedLengthAndFlag = buffer.readUInt16LE(offset);
|
||||
chunk.has_subchunks = combinedLengthAndFlag > 32768;
|
||||
chunk.data_len = chunk.has_subchunks ? combinedLengthAndFlag - 32768 : combinedLengthAndFlag;
|
||||
offset += 2;
|
||||
chunk.chunk_data = buffer.subarray(offset, offset + chunk.data_len);
|
||||
|
||||
dataDecoder(chunk);
|
||||
return chunk;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
const { CHUNK_HEADER_SIZE } = require('../../constants');
|
||||
const chunk = require('../chunk');
|
||||
const packetHeaderChunk = require('../packet-header-chunk');
|
||||
const dataTrackerListChunk = require('./data-tracker-list-chunk');
|
||||
|
||||
function decodeDataPacketChunk(dataPacketChunk) {
|
||||
if (dataPacketChunk.has_subchunks && dataPacketChunk.chunk_data) {
|
||||
let offset = 0;
|
||||
while (offset < dataPacketChunk.data_len) {
|
||||
const chunkId = dataPacketChunk.chunk_data.readUInt16LE(offset);
|
||||
switch (chunkId) {
|
||||
case 0x0000:
|
||||
dataPacketChunk.packet_header = packetHeaderChunk(dataPacketChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += dataPacketChunk.packet_header.data_len;
|
||||
break;
|
||||
case 0x0001:
|
||||
dataPacketChunk.tracker_list = dataTrackerListChunk(dataPacketChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += dataPacketChunk.tracker_list.data_len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodeDataPacketChunk);
|
||||
@@ -0,0 +1,41 @@
|
||||
const { CHUNK_HEADER_SIZE } = require('../../constants');
|
||||
const chunk = require('../chunk');
|
||||
const dataTrackerFieldChunk = require('./data-tracker-field-chunk');
|
||||
|
||||
function decodeTrackerChunk(trackerChunk) {
|
||||
if (trackerChunk.chunk_data && trackerChunk.data_len > 0) {
|
||||
let offset = 0;
|
||||
while (offset < trackerChunk.data_len) {
|
||||
const trackerFieldChunk = dataTrackerFieldChunk(trackerChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += trackerFieldChunk.data_len;
|
||||
switch (trackerFieldChunk.id) {
|
||||
case 0x0000:
|
||||
trackerChunk.pos = trackerFieldChunk;
|
||||
break;
|
||||
case 0x0001:
|
||||
trackerChunk.speed = trackerFieldChunk;
|
||||
break;
|
||||
case 0x0002:
|
||||
trackerChunk.ori = trackerFieldChunk;
|
||||
break;
|
||||
case 0x0003:
|
||||
trackerChunk.status = trackerFieldChunk;
|
||||
break;
|
||||
case 0x0004:
|
||||
trackerChunk.accel = trackerFieldChunk;
|
||||
break;
|
||||
case 0x0005:
|
||||
trackerChunk.trgtpos = trackerFieldChunk;
|
||||
break;
|
||||
case 0x0006:
|
||||
trackerChunk.timestamp = trackerFieldChunk;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodeTrackerChunk);
|
||||
@@ -1,29 +1,43 @@
|
||||
const Parser = require('binary-parser').Parser;
|
||||
/* eslint-disable no-case-declarations */
|
||||
const chunk = require('../chunk');
|
||||
|
||||
module.exports = new Parser()
|
||||
.uint16le('id')
|
||||
.uint16le('data_len', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return Number.parseInt(binary.substring(1), 2);
|
||||
},
|
||||
})
|
||||
.seek(-2)
|
||||
.uint16le('has_subchunks', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return binary.charAt(0) === '1';
|
||||
},
|
||||
})
|
||||
.choice('data', {
|
||||
tag: 'id',
|
||||
choices: {
|
||||
0x0000: new Parser().floatle('x').floatle('y').floatle('z'),
|
||||
0x0001: new Parser().floatle('x').floatle('y').floatle('z'),
|
||||
0x0002: new Parser().floatle('x').floatle('y').floatle('z'),
|
||||
0x0003: new Parser().floatle('validity'),
|
||||
0x0004: new Parser().floatle('x').floatle('y').floatle('z'),
|
||||
0x0005: new Parser().floatle('x').floatle('y').floatle('z'),
|
||||
0x0006: new Parser().uint64le('tracker_timestamp'),
|
||||
},
|
||||
});
|
||||
function readXYZ(trackerFieldChunk, prefix) {
|
||||
if (prefix === undefined) {
|
||||
prefix = '';
|
||||
}
|
||||
|
||||
trackerFieldChunk[`${prefix}x`] = trackerFieldChunk.chunk_data.readFloatLE(0);
|
||||
trackerFieldChunk[`${prefix}y`] = trackerFieldChunk.chunk_data.readFloatLE(4);
|
||||
trackerFieldChunk[`${prefix}z`] = trackerFieldChunk.chunk_data.readFloatLE(8);
|
||||
}
|
||||
function decodeTrackerFieldChunk(trackerFieldChunk) {
|
||||
if (trackerFieldChunk.id !== undefined) {
|
||||
switch (trackerFieldChunk.id) {
|
||||
case 0x0000:
|
||||
readXYZ(trackerFieldChunk, 'pos_');
|
||||
break;
|
||||
case 0x0001:
|
||||
readXYZ(trackerFieldChunk, 'speed_');
|
||||
break;
|
||||
case 0x0002:
|
||||
readXYZ(trackerFieldChunk, 'ori_');
|
||||
break;
|
||||
case 0x0003:
|
||||
trackerFieldChunk.validity = trackerFieldChunk.chunk_data.readFloatLE();
|
||||
break;
|
||||
case 0x0004:
|
||||
readXYZ(trackerFieldChunk, 'accel_');
|
||||
break;
|
||||
case 0x0005:
|
||||
readXYZ(trackerFieldChunk, 'trgtpos_');
|
||||
break;
|
||||
case 0x0006:
|
||||
trackerFieldChunk.tracker_timestamp = trackerFieldChunk.chunk_data.readBigUInt64LE();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodeTrackerFieldChunk);
|
||||
|
||||
@@ -1,24 +1,17 @@
|
||||
module.exports = (buffer) => {
|
||||
const trackerList = {
|
||||
trackers: [],
|
||||
};
|
||||
const { CHUNK_HEADER_SIZE } = require('../../constants');
|
||||
const chunk = require('../chunk');
|
||||
const dataTrackerChunk = require('./data-tracker-chunk');
|
||||
|
||||
function decodeDataTrackerListChunk(dataTrackerListChunk) {
|
||||
dataTrackerListChunk.trackers = {};
|
||||
|
||||
// TODO(jwetzell): add error handling
|
||||
let offset = 0;
|
||||
while (offset < buffer.length) {
|
||||
const trackerChunk = {};
|
||||
trackerChunk.id = buffer.readUInt16LE(offset);
|
||||
offset += 2;
|
||||
|
||||
// NOTE(jwetzell): this data is split up as 1 bit for has_subchunks and 15 bits for the data_len
|
||||
const tempBytesAsBinary = buffer.readUInt16LE(offset).toString(2);
|
||||
trackerChunk.has_subchunks = tempBytesAsBinary.charAt(0) === '0';
|
||||
trackerChunk.data_len = parseInt(tempBytesAsBinary.substring(1), 2);
|
||||
offset += 2;
|
||||
trackerChunk.data = buffer.subarray(offset, offset + trackerChunk.data_len);
|
||||
while (offset < dataTrackerListChunk.chunk_data.length) {
|
||||
const trackerChunk = dataTrackerChunk(dataTrackerListChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += trackerChunk.data_len;
|
||||
trackerList.trackers.push(trackerChunk);
|
||||
dataTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
|
||||
}
|
||||
|
||||
return trackerList;
|
||||
};
|
||||
}
|
||||
module.exports = (buffer) => chunk(buffer, decodeDataTrackerListChunk);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
const TrackerListChunk = require('./data-tracker-list-chunk');
|
||||
const TrackerFieldChunk = require('./data-tracker-field-chunk');
|
||||
|
||||
module.exports = {
|
||||
TrackerFieldChunk,
|
||||
TrackerListChunk,
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
const Chunk = require('./chunk');
|
||||
const PacketHeaderChunk = require('./packet-header-chunk');
|
||||
const Packet = require('./packet');
|
||||
const Info = require('./info');
|
||||
const Data = require('./data');
|
||||
|
||||
module.exports = {
|
||||
Chunk,
|
||||
PacketHeaderChunk,
|
||||
Packet,
|
||||
Info: {
|
||||
...Info,
|
||||
},
|
||||
Data: {
|
||||
...Data,
|
||||
},
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
const SystemNameChunk = require('./info-system-name-chunk');
|
||||
const TrackerListChunk = require('./info-tracker-list-chunk');
|
||||
|
||||
module.exports = {
|
||||
SystemNameChunk,
|
||||
TrackerListChunk,
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
const { CHUNK_HEADER_SIZE } = require('../../constants');
|
||||
const chunk = require('../chunk');
|
||||
const packetHeaderChunk = require('../packet-header-chunk');
|
||||
const infoSystemNameChunk = require('./info-system-name-chunk');
|
||||
const infoTrackerListChunk = require('./info-tracker-list-chunk');
|
||||
|
||||
function decodeInfoPacketChunk(infoPacketChunk) {
|
||||
if (infoPacketChunk.has_subchunks && infoPacketChunk.chunk_data) {
|
||||
let offset = 0;
|
||||
while (offset < infoPacketChunk.data_len) {
|
||||
const chunkId = infoPacketChunk.chunk_data.readUInt16LE(offset);
|
||||
switch (chunkId) {
|
||||
case 0x0000:
|
||||
infoPacketChunk.packet_header = packetHeaderChunk(infoPacketChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += infoPacketChunk.packet_header.data_len;
|
||||
break;
|
||||
case 0x0001:
|
||||
infoPacketChunk.system_name = infoSystemNameChunk(infoPacketChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += infoPacketChunk.system_name.data_len;
|
||||
break;
|
||||
case 0x0002:
|
||||
infoPacketChunk.tracker_list = infoTrackerListChunk(infoPacketChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += infoPacketChunk.tracker_list.data_len;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodeInfoPacketChunk);
|
||||
@@ -1,3 +1,9 @@
|
||||
const Parser = require('binary-parser').Parser;
|
||||
const chunk = require('../chunk');
|
||||
|
||||
module.exports = new Parser().string('system_name', { greedy: true });
|
||||
function decodeSystemNameChunk(systemNameChunk) {
|
||||
if (systemNameChunk.chunk_data !== undefined && systemNameChunk.data_len !== undefined) {
|
||||
systemNameChunk.system_name = systemNameChunk.chunk_data.subarray(0, systemNameChunk.data_len).toString();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodeSystemNameChunk);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
const { CHUNK_HEADER_SIZE } = require('../../constants');
|
||||
const chunk = require('../chunk');
|
||||
const infoTrackerNameChunk = require('./info-tracker-name-chunk');
|
||||
|
||||
function decodeInfoTrackerChunk(infoTrackerChunk) {
|
||||
if (infoTrackerChunk.has_subchunks && infoTrackerChunk.chunk_data) {
|
||||
let offset = 0;
|
||||
while (offset < infoTrackerChunk.data_len) {
|
||||
const chunkId = infoTrackerChunk.chunk_data.readUInt16LE(offset);
|
||||
switch (chunkId) {
|
||||
case 0x0000:
|
||||
infoTrackerChunk.tracker_name = infoTrackerNameChunk(infoTrackerChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += infoTrackerChunk.tracker_name.data_len;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodeInfoTrackerChunk);
|
||||
@@ -1,39 +1,17 @@
|
||||
const Parser = require('binary-parser').Parser;
|
||||
const { CHUNK_HEADER_SIZE } = require('../../constants');
|
||||
const chunk = require('../chunk');
|
||||
const infoTrackerChunk = require('./info-tracker-chunk');
|
||||
|
||||
const infoTrackerNameParser = new Parser()
|
||||
.uint16le('id')
|
||||
.uint16le('data_len', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return Number.parseInt(binary.substring(1), 2);
|
||||
},
|
||||
})
|
||||
.seek(-2)
|
||||
.uint16le('has_subchunks', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return binary.charAt(0) === '1';
|
||||
},
|
||||
})
|
||||
.string('tracker_name', { length: 'data_len' });
|
||||
|
||||
const infoTrackerParser = new Parser()
|
||||
.uint16le('id')
|
||||
.uint16le('data_len', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return Number.parseInt(binary.substring(1), 2);
|
||||
},
|
||||
})
|
||||
.seek(-2)
|
||||
.uint16le('has_subchunks', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return binary.charAt(0) === '1';
|
||||
},
|
||||
})
|
||||
.nest('tracker_name', {
|
||||
type: infoTrackerNameParser,
|
||||
});
|
||||
|
||||
module.exports = new Parser().array('trackers', { type: infoTrackerParser, readUntil: 'eof' });
|
||||
function decodeInfoTrackerListChunk(infoTrackerListChunk) {
|
||||
infoTrackerListChunk.trackers = {};
|
||||
if (infoTrackerListChunk.has_subchunks && infoTrackerListChunk.chunk_data) {
|
||||
let offset = 0;
|
||||
while (offset < infoTrackerListChunk.data_len) {
|
||||
const trackerChunk = infoTrackerChunk(infoTrackerListChunk.chunk_data.subarray(offset));
|
||||
offset += CHUNK_HEADER_SIZE;
|
||||
offset += trackerChunk.data_len;
|
||||
infoTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = (buffer) => chunk(buffer, decodeInfoTrackerListChunk);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
const chunk = require('../chunk');
|
||||
|
||||
function decodeTrackerNameChunk(trackerNameChunk) {
|
||||
if (trackerNameChunk.chunk_data !== undefined && trackerNameChunk.data_len !== undefined) {
|
||||
trackerNameChunk.tracker_name = trackerNameChunk.chunk_data.subarray(0, trackerNameChunk.data_len).toString();
|
||||
}
|
||||
}
|
||||
module.exports = (buffer) => chunk(buffer, decodeTrackerNameChunk);
|
||||
@@ -1,9 +1,12 @@
|
||||
const Parser = require('binary-parser').Parser;
|
||||
const chunk = require('./chunk');
|
||||
|
||||
module.exports = new Parser()
|
||||
.uint64le('packet_timestamp')
|
||||
.uint8('version_high')
|
||||
.uint8('version_low')
|
||||
.uint8('frame_id')
|
||||
.uint8('frame_packet_count')
|
||||
.seek(4);
|
||||
function decodePacketHeaderChunk(packetHeaderChunk) {
|
||||
// TODO(jwetzell): remove the string conversion
|
||||
packetHeaderChunk.packet_timestamp = packetHeaderChunk.chunk_data.readBigUInt64LE(0);
|
||||
packetHeaderChunk.version_high = packetHeaderChunk.chunk_data.readUInt8(8);
|
||||
packetHeaderChunk.version_low = packetHeaderChunk.chunk_data.readUInt8(9);
|
||||
packetHeaderChunk.frame_id = packetHeaderChunk.chunk_data.readUInt8(10);
|
||||
packetHeaderChunk.frame_packet_count = packetHeaderChunk.chunk_data.readUInt8(11);
|
||||
}
|
||||
|
||||
module.exports = (buffer) => chunk(buffer, decodePacketHeaderChunk);
|
||||
|
||||
+13
-17
@@ -1,18 +1,14 @@
|
||||
const Parser = require('binary-parser').Parser;
|
||||
const dataPacketChunk = require('./data/data-packet-chunk');
|
||||
const infoPacketChunk = require('./info/info-packet-chunk');
|
||||
|
||||
module.exports = new Parser()
|
||||
.uint16le('id')
|
||||
.uint16le('data_len', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return Number.parseInt(binary.substring(1), 2);
|
||||
},
|
||||
})
|
||||
.seek(-2)
|
||||
.uint16le('has_subchunks', {
|
||||
formatter: (item) => {
|
||||
const binary = item.toString(2).padStart(16, '0');
|
||||
return binary.charAt(0) === '1';
|
||||
},
|
||||
})
|
||||
.buffer('chunk_data', { readUntil: 'eof' });
|
||||
module.exports = (buffer) => {
|
||||
const chunkId = buffer.readUInt16LE();
|
||||
switch (chunkId) {
|
||||
case 0x6756:
|
||||
return infoPacketChunk(buffer);
|
||||
case 0x6755:
|
||||
return dataPacketChunk(buffer);
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
+16
-16
@@ -1,14 +1,13 @@
|
||||
const dataChunk = require('./encoders/data/data-chunk');
|
||||
const { MAX_UDP_PACKET_SIZE, PACKET_HEADER_SIZE, CHUNK_HEADER_SIZE } = require('./constants');
|
||||
const dataPacketChunk = require('./encoders/data/data-packet-chunk');
|
||||
const dataTrackerListChunk = require('./encoders/data/data-tracker-list-chunk');
|
||||
const infoChunk = require('./encoders/info/info-chunk');
|
||||
const infoPacketChunk = require('./encoders/info/info-packet-chunk');
|
||||
const infoSystemNameChunk = require('./encoders/info/info-system-name-chunk');
|
||||
const infoTrackerListChunk = require('./encoders/info/info-tracker-list-chunk');
|
||||
const packetHeaderChunk = require('./encoders/packet-header-chunk');
|
||||
|
||||
const MAX_TRACKER_LIST_SIZE = 1000;
|
||||
|
||||
class Encoder {
|
||||
constructor(systemName, versionHigh, versionLow) {
|
||||
constructor(systemName, versionHigh = 2, versionLow = 3) {
|
||||
this.systemName = systemName;
|
||||
this.versionHigh = versionHigh;
|
||||
this.versionLow = versionLow;
|
||||
@@ -17,6 +16,8 @@ class Encoder {
|
||||
}
|
||||
|
||||
getInfoPackets(timestamp, trackers) {
|
||||
const systemNameChunk = infoSystemNameChunk(this.systemName);
|
||||
|
||||
const trackerChunks = trackers.map((tracker) => tracker.getInfoChunk());
|
||||
|
||||
const infoPackets = [];
|
||||
@@ -24,16 +25,16 @@ class Encoder {
|
||||
const trackerChunksLists = [];
|
||||
let currentTrackerList = [];
|
||||
|
||||
let currentTrackerListSize = 0;
|
||||
let currentInfoPacketSize = PACKET_HEADER_SIZE + systemNameChunk.length + CHUNK_HEADER_SIZE;
|
||||
|
||||
trackerChunks.forEach((trackerChunk) => {
|
||||
if (currentTrackerListSize + trackerChunk.length > MAX_TRACKER_LIST_SIZE) {
|
||||
if (currentInfoPacketSize + trackerChunk.length > MAX_UDP_PACKET_SIZE) {
|
||||
trackerChunksLists.push(currentTrackerList);
|
||||
currentTrackerList = [];
|
||||
currentTrackerListSize = 0;
|
||||
currentInfoPacketSize = 0;
|
||||
}
|
||||
currentTrackerList.push(trackerChunk);
|
||||
currentTrackerListSize += trackerChunk.length;
|
||||
currentInfoPacketSize += trackerChunk.length;
|
||||
});
|
||||
trackerChunksLists.push(currentTrackerList);
|
||||
const header = packetHeaderChunk(
|
||||
@@ -44,7 +45,7 @@ class Encoder {
|
||||
trackerChunksLists.length
|
||||
);
|
||||
trackerChunksLists.forEach((trackerChunkList) => {
|
||||
infoPackets.push(infoChunk(header, infoSystemNameChunk(this.systemName), infoTrackerListChunk(trackerChunkList)));
|
||||
infoPackets.push(infoPacketChunk(header, systemNameChunk, infoTrackerListChunk(trackerChunkList)));
|
||||
});
|
||||
this.dataFrameId += 1;
|
||||
if (this.dataFrameId > 255) {
|
||||
@@ -55,22 +56,21 @@ class Encoder {
|
||||
|
||||
getDataPackets(timestamp, trackers) {
|
||||
const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk());
|
||||
|
||||
const dataPackets = [];
|
||||
|
||||
const trackerChunksLists = [];
|
||||
let currentTrackerList = [];
|
||||
|
||||
let currentTrackerListSize = 0;
|
||||
let currentDataPacketSize = PACKET_HEADER_SIZE + CHUNK_HEADER_SIZE;
|
||||
|
||||
allTrackerChunks.forEach((trackerChunk) => {
|
||||
if (currentTrackerListSize + trackerChunk.length > MAX_TRACKER_LIST_SIZE) {
|
||||
if (currentDataPacketSize + trackerChunk.length > MAX_UDP_PACKET_SIZE) {
|
||||
trackerChunksLists.push(currentTrackerList);
|
||||
currentTrackerList = [];
|
||||
currentTrackerListSize = 0;
|
||||
currentDataPacketSize = 0;
|
||||
}
|
||||
currentTrackerList.push(trackerChunk);
|
||||
currentTrackerListSize += trackerChunk.length;
|
||||
currentDataPacketSize += trackerChunk.length;
|
||||
});
|
||||
trackerChunksLists.push(currentTrackerList);
|
||||
|
||||
@@ -82,7 +82,7 @@ class Encoder {
|
||||
trackerChunksLists.length
|
||||
);
|
||||
trackerChunksLists.forEach((trackerChunks) => {
|
||||
dataPackets.push(dataChunk(header, dataTrackerListChunk(trackerChunks)));
|
||||
dataPackets.push(dataPacketChunk(header, dataTrackerListChunk(trackerChunks)));
|
||||
});
|
||||
this.dataFrameId += 1;
|
||||
if (this.dataFrameId > 255) {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
const chunk = require('../chunk');
|
||||
|
||||
module.exports = (trackerId, fieldChunks) => chunk(trackerId, Buffer.concat(fieldChunks), true);
|
||||
module.exports = (trackerId, fieldChunks) => chunk(trackerId, Buffer.concat(fieldChunks), fieldChunks.length > 0);
|
||||
|
||||
@@ -2,9 +2,6 @@ const chunk = require('../chunk');
|
||||
|
||||
module.exports = (timestamp) => {
|
||||
const buf = Buffer.alloc(8);
|
||||
const timestampHigh = timestamp.toString(2).padStart(64, '0').substring(0, 32);
|
||||
const timestampLow = timestamp.toString(2).padStart(64, '0').substring(32);
|
||||
buf.writeUInt32LE(parseInt(timestampLow, 2));
|
||||
buf.writeUInt32LE(parseInt(timestampHigh, 2), 4);
|
||||
buf.writeBigUInt64LE(BigInt(timestamp));
|
||||
return chunk(0x0006, buf, false);
|
||||
};
|
||||
|
||||
@@ -5,11 +5,7 @@ module.exports = (timestamp, versionHigh, versionLow, frameId, framePacketCount)
|
||||
throw new Error('frame id must be >= 0 and <= 255');
|
||||
}
|
||||
const packetHeader = Buffer.alloc(12);
|
||||
const timestampHigh = timestamp.toString(2).padStart(64, '0').substring(0, 32);
|
||||
const timestampLow = timestamp.toString(2).padStart(64, '0').substring(32);
|
||||
packetHeader.writeUInt32LE(parseInt(timestampLow, 2));
|
||||
packetHeader.writeUInt32LE(parseInt(timestampHigh, 2), 4);
|
||||
|
||||
packetHeader.writeBigUInt64LE(BigInt(timestamp));
|
||||
packetHeader.writeUint8(versionHigh, 8);
|
||||
packetHeader.writeUint8(versionLow, 9);
|
||||
packetHeader.writeUint8(frameId, 10);
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/* eslint-disable no-case-declarations */
|
||||
/* eslint-disable no-param-reassign */
|
||||
const { Parser } = require('binary-parser');
|
||||
const Decoders = require('../../decoders');
|
||||
|
||||
class DataPacket {
|
||||
constructor(packet) {
|
||||
this.packet = packet;
|
||||
this.subChunks = [];
|
||||
// console.log(this.packet);
|
||||
if (this.packet.has_subchunks) {
|
||||
this.subChunkParser = new Parser().array('chunks', {
|
||||
type: Decoders.Chunk,
|
||||
lengthInBytes: this.packet.data_len,
|
||||
});
|
||||
this.subChunks = this.subChunkParser.parse(this.packet.chunk_data)?.chunks;
|
||||
this.subChunks = this.subChunks.map((subChunk) => {
|
||||
let populatedSubChunk = {};
|
||||
populatedSubChunk.data_len_valid = subChunk.chunk_data.length === subChunk.data_len;
|
||||
switch (subChunk.id) {
|
||||
case 0:
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
...Decoders.PacketHeaderChunk.parse(subChunk.chunk_data),
|
||||
};
|
||||
break;
|
||||
case 1:
|
||||
const dataTrackerList = Decoders.Data.TrackerListChunk(subChunk.chunk_data);
|
||||
dataTrackerList.trackers?.forEach((tracker) => {
|
||||
if (tracker.data && tracker.data_len > 0) {
|
||||
const fields = new Parser()
|
||||
.array('fields', {
|
||||
type: Decoders.Data.TrackerFieldChunk,
|
||||
lengthInBytes: tracker.data_len,
|
||||
})
|
||||
.parse(tracker.data);
|
||||
if (fields.fields) {
|
||||
fields.fields.forEach((field) => {
|
||||
switch (field.id) {
|
||||
case 0x0000:
|
||||
tracker.pos = field.data;
|
||||
break;
|
||||
case 0x0001:
|
||||
tracker.speed = field.data;
|
||||
break;
|
||||
case 0x0002:
|
||||
tracker.ori = field.data;
|
||||
break;
|
||||
case 0x0003:
|
||||
tracker.status = field.data;
|
||||
break;
|
||||
case 0x0004:
|
||||
tracker.accel = field.data;
|
||||
break;
|
||||
case 0x0005:
|
||||
tracker.trgtpos = field.data;
|
||||
break;
|
||||
case 0x0006:
|
||||
tracker.timestamp = field.data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
...dataTrackerList,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
};
|
||||
break;
|
||||
}
|
||||
return populatedSubChunk;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getHeaderPacket() {
|
||||
return this.subChunks.find((subChunk) => subChunk.id === 0x0000);
|
||||
}
|
||||
|
||||
getSystemPacket() {
|
||||
return this.subChunks.find((subChunk) => subChunk.id === 0x0001);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DataPacket;
|
||||
@@ -1,7 +0,0 @@
|
||||
const DataPacket = require('./data-packet');
|
||||
const InfoPacket = require('./info-packet');
|
||||
|
||||
module.exports = {
|
||||
DataPacket,
|
||||
InfoPacket,
|
||||
};
|
||||
@@ -1,56 +0,0 @@
|
||||
const { Parser } = require('binary-parser');
|
||||
const Decoders = require('../../decoders');
|
||||
|
||||
class InfoPacket {
|
||||
constructor(packet) {
|
||||
this.packet = packet;
|
||||
this.subChunks = [];
|
||||
if (this.packet.has_subchunks) {
|
||||
this.subChunkParser = new Parser().array('chunks', {
|
||||
type: Decoders.Chunk,
|
||||
lengthInBytes: this.packet.data_len,
|
||||
});
|
||||
this.subChunks = this.subChunkParser.parse(this.packet.chunk_data)?.chunks;
|
||||
this.subChunks = this.subChunks.map((subChunk) => {
|
||||
let populatedSubChunk = {};
|
||||
populatedSubChunk.data_len_valid = subChunk.chunk_data.length === subChunk.data_len;
|
||||
switch (subChunk.id) {
|
||||
case 0:
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
...Decoders.PacketHeaderChunk.parse(subChunk.chunk_data),
|
||||
};
|
||||
break;
|
||||
case 1:
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
...Decoders.Info.SystemNameChunk.parse(subChunk.chunk_data),
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
...Decoders.Info.TrackerListChunk.parse(subChunk.chunk_data),
|
||||
};
|
||||
break;
|
||||
default:
|
||||
populatedSubChunk = {
|
||||
...subChunk,
|
||||
};
|
||||
break;
|
||||
}
|
||||
return populatedSubChunk;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getHeaderPacket() {
|
||||
return this.subChunks.find((subChunk) => subChunk.id === 0x0000);
|
||||
}
|
||||
|
||||
getSystemPacket() {
|
||||
return this.subChunks.find((subChunk) => subChunk.id === 0x0001);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InfoPacket;
|
||||
Reference in New Issue
Block a user