42 Commits

Author SHA1 Message Date
jwetzell 6f6ebece34 2.0.0 2025-01-06 21:50:15 -06:00
jwetzell 6580f66e91 align structure more with underlying chunk layout 2025-01-06 21:49:08 -06:00
jwetzell acac519e9a Merge pull request #53 from jwetzell/dependabot/npm_and_yarn/types/node-22.10.2
Bump @types/node from 22.10.1 to 22.10.2
2024-12-25 09:41:14 -06:00
jwetzell 03e47a98a0 clean up Decoder properties 2024-12-19 21:07:57 -06:00
jwetzell f77e8815d1 simpler logging on benchmark 2024-12-19 19:32:00 -06:00
jwetzell 86ea701a8e fix import on benchmark 2024-12-19 19:29:26 -06:00
dependabot[bot] c5ef7180c7 Bump @types/node from 22.10.1 to 22.10.2
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.10.1 to 22.10.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 12:13:45 +00:00
jwetzell 3a44b9d79e Merge pull request #52 from jwetzell/dependabot/npm_and_yarn/prettier-3.4.2
Bump prettier from 3.4.1 to 3.4.2
2024-12-15 22:48:15 -06:00
dependabot[bot] e7a03383e6 Bump prettier from 3.4.1 to 3.4.2
Bumps [prettier](https://github.com/prettier/prettier) from 3.4.1 to 3.4.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.4.1...3.4.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 12:16:15 +00:00
jwetzell 7edba830a5 Merge pull request #50 from jwetzell/dependabot/npm_and_yarn/prettier-3.4.1
Bump prettier from 3.3.3 to 3.4.1
2024-12-03 13:17:03 -06:00
dependabot[bot] 7749596859 Bump prettier from 3.3.3 to 3.4.1
Bumps [prettier](https://github.com/prettier/prettier) from 3.3.3 to 3.4.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.3.3...3.4.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-02 15:44:57 +00:00
jwetzell b2ca7467ce Merge pull request #51 from jwetzell/dependabot/npm_and_yarn/types/node-22.10.1
Bump @types/node from 22.9.3 to 22.10.1
2024-12-02 09:43:29 -06:00
dependabot[bot] 431e9de9a1 Bump @types/node from 22.9.3 to 22.10.1
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.9.3 to 22.10.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-02 13:33:23 +00:00
jwetzell 934f572f38 Merge pull request #48 from jwetzell/dependabot/npm_and_yarn/types/node-22.9.3
Bump @types/node from 22.9.0 to 22.9.3
2024-11-25 13:45:06 -06:00
jwetzell f5c2de983f Merge pull request #49 from jwetzell/dependabot/npm_and_yarn/typescript-5.7.2
Bump typescript from 5.6.3 to 5.7.2
2024-11-25 13:44:56 -06:00
dependabot[bot] e367f1def9 Bump typescript from 5.6.3 to 5.7.2
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.3 to 5.7.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.3...v5.7.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 12:35:31 +00:00
dependabot[bot] 90f1deb43d Bump @types/node from 22.9.0 to 22.9.3
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.9.0 to 22.9.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 12:35:19 +00:00
jwetzell 23c4743ee8 Merge pull request #45 from jwetzell/dependabot/npm_and_yarn/types/node-22.9.0
Bump @types/node from 22.8.7 to 22.9.0
2024-11-18 08:22:49 -06:00
dependabot[bot] e132a22578 Bump @types/node from 22.8.7 to 22.9.0
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.8.7 to 22.9.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 12:28:11 +00:00
jwetzell 46368ad89b lint 2024-11-04 19:25:41 -06:00
jwetzell 4f846ccbd6 add eslint and format scripts 2024-11-04 19:25:19 -06:00
jwetzell ca2848f92a Merge pull request #44 from jwetzell/dependabot/npm_and_yarn/types/node-22.8.7
Bump @types/node from 22.8.1 to 22.8.7
2024-11-04 13:36:28 -06:00
dependabot[bot] a3f89ec528 Bump @types/node from 22.8.1 to 22.8.7
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.8.1 to 22.8.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 13:03:08 +00:00
jwetzell 01236ca7d3 Merge pull request #43 from jwetzell/dependabot/npm_and_yarn/types/node-22.8.1
Bump @types/node from 22.7.7 to 22.8.1
2024-10-28 09:59:32 -05:00
dependabot[bot] db436f34ed Bump @types/node from 22.7.7 to 22.8.1
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.7.7 to 22.8.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 12:27:51 +00:00
jwetzell c05e2447b0 bump version to 1.1.0 2024-10-25 12:12:02 -05:00
jwetzell 4abc3968c1 Merge pull request #42 from jwetzell/esm-and-cjs
add support for bundling both esm and cjs versions
2024-10-25 12:11:36 -05:00
jwetzell 06a974e557 fix import in examples 2024-10-25 12:10:45 -05:00
jwetzell 7a5b027c68 add support for bundling both esm and cjs versions 2024-10-25 12:09:56 -05:00
jwetzell afebfe75b1 update vscode settings 2024-10-23 16:50:19 -05:00
jwetzell 3e51737881 bump version to 1.0.0 2024-10-23 16:48:32 -05:00
jwetzell 3a249ff52d sync package-lock 2024-10-23 16:47:53 -05:00
jwetzell 9273f5a1a5 add examples from README to examples folder 2024-10-23 16:47:24 -05:00
jwetzell 82d4e17ec9 Merge pull request #41 from jwetzell/remove-buffer
replace NodeJS buffer with Uint8Array
2024-10-23 16:47:06 -05:00
jwetzell 8710e75a93 update example in README 2024-10-23 16:46:12 -05:00
jwetzell 4eaedcdfaa replace NodeJS buffer with Uint8Array 2024-10-23 16:38:16 -05:00
jwetzell 90e1bd09a0 Create LICENSE 2024-10-22 08:36:21 -05:00
jwetzell 1358158333 Change license to MIT in package.json 2024-10-22 08:36:00 -05:00
jwetzell 521ef895d8 Merge pull request #39 from jwetzell/dependabot/npm_and_yarn/typescript-5.6.3
Bump typescript from 5.6.2 to 5.6.3
2024-10-21 10:26:37 -05:00
jwetzell d0645d4c93 Merge pull request #40 from jwetzell/dependabot/npm_and_yarn/types/node-22.7.7
Bump @types/node from 22.7.4 to 22.7.7
2024-10-21 10:26:27 -05:00
dependabot[bot] 8d99c0a647 Bump @types/node from 22.7.4 to 22.7.7
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.7.4 to 22.7.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 12:15:59 +00:00
dependabot[bot] efc69c9345 Bump typescript from 5.6.2 to 5.6.3
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.6.2 to 5.6.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.6.2...v5.6.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 13:05:46 +00:00
66 changed files with 4373 additions and 461 deletions
+12
View File
@@ -0,0 +1,12 @@
module.exports = {
env: {
node: true,
commonjs: true,
es2021: true,
},
extends: ['airbnb', 'prettier'],
parserOptions: {
ecmaVersion: 'latest',
},
ignorePatterns: ['**/node_modules', '**/dist'],
};
+2 -2
View File
@@ -2,7 +2,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": true
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Joel Wetzell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+12 -4
View File
@@ -13,8 +13,16 @@ typesecript implementation of the [PosiStageNet protocol](https://github.com/vyv
const { Decoder } = require('@jwetzell/posistagenet')
const decoder = new Decoder()
const infoPacketBuffer = Buffer.from('5667348000000c0001000000000000000203010101000b00536572766572204e616d650200118001000d8000000900547261636b65722031','hex')
const dataPacketBuffer = Buffer.from('5567288000000c00010000000000000002030101010014800100108000000c000000803f0000803f0000803f','hex')
const infoPacketBuffer = new Uint8Array([
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
]);
const dataPacketBuffer = new Uint8Array([
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
]);
decoder.decode(infoPacketBuffer)
decoder.decode(dataPacketBuffer)
@@ -49,12 +57,12 @@ const infoPackets = encoder.getInfoPackets(timestamp, trackers)
dataPackets.forEach((dataPacket)=>{
console.log('send packet somehow')
console.log(dataPacket.toString('hex'))
console.log(dataPacket)
})
infoPackets.forEach((infoPacket)=>{
console.log('send packet somehow')
console.log(infoPacket.toString('hex'))
console.log(infoPacket)
})
```
+6 -6
View File
@@ -1,4 +1,4 @@
const { Encoder, Decoder, Tracker } = require('./dist');
const { Encoder, Decoder, Tracker } = require('./dist/cjs');
const testSizes = [1, 10, 100, 1000];
@@ -40,7 +40,7 @@ function benchmark(trackerCount, iterations) {
for (let index = 0; index < iterations; index += 1) {
latestEncodedPackets = encoder.getDataPackets(Date.now(), trackers);
}
benchmarkResults.data.encode = `${(performance.now() - dataEncoderStart).toFixed(2)}ms`;
benchmarkResults.data.encode = performance.now() - dataEncoderStart;
const dataDecodedStart = performance.now();
for (let index = 0; index < iterations; index += 1) {
@@ -48,14 +48,14 @@ function benchmark(trackerCount, iterations) {
decoder.decode(packet);
});
}
benchmarkResults.data.decode = `${(performance.now() - dataDecodedStart).toFixed(2)}ms`;
benchmarkResults.data.decode = performance.now() - dataDecodedStart;
// INFO
const infoEncoderStart = performance.now();
for (let index = 0; index < iterations; index += 1) {
latestEncodedPackets = encoder.getInfoPackets(Date.now(), trackers);
}
benchmarkResults.info.encode = `${(performance.now() - infoEncoderStart).toFixed(2)}ms`;
benchmarkResults.info.encode = performance.now() - infoEncoderStart;
const infoDecodeStart = performance.now();
for (let index = 0; index < iterations; index += 1) {
@@ -63,9 +63,9 @@ function benchmark(trackerCount, iterations) {
decoder.decode(packet);
});
}
benchmarkResults.info.decode = `${(performance.now() - infoDecodeStart).toFixed(2)}ms`;
benchmarkResults.info.decode = performance.now() - infoDecodeStart;
console.table(benchmarkResults);
console.log(benchmarkResults);
}
testSizes.forEach((iterations) => {
+24
View File
@@ -0,0 +1,24 @@
const { Decoder } = require('../dist/cjs');
const decoder = new Decoder();
const infoPacketBuffer = new Uint8Array([
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
]);
const dataPacketBuffer = new Uint8Array([
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
]);
decoder.decode(infoPacketBuffer);
decoder.decode(dataPacketBuffer);
// the system_name from info packets if available
console.log(decoder.systemName);
// 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);
+26
View File
@@ -0,0 +1,26 @@
const { Encoder, Tracker } = require('../dist/cjs');
const encoder = new Encoder('Server Name', 2, 3); // server name, version high, version low
const trackers = [];
const tracker = new Tracker(1, 'Tracker 1'); // id, name
tracker.setPos(1.0, 1.0, 1.0); // x, y, z
trackers.push(tracker);
const timestamp = 1;
// these two calls return an array of Buffers due to potential splitting that might take place because of max UDP packet size
const dataPackets = encoder.getDataPackets(timestamp, trackers);
const infoPackets = encoder.getInfoPackets(timestamp, trackers);
dataPackets.forEach((dataPacket) => {
console.log('send packet somehow');
console.log(dataPacket);
});
infoPackets.forEach((infoPacket) => {
console.log('send packet somehow');
console.log(infoPacket);
});
+8 -10
View File
@@ -1,6 +1,6 @@
// recreation of psn_client.cpp example from https://github.com/vyv/psn-cpp
const dgram = require('dgram');
const { Decoder } = require('../dist');
const { Decoder } = require('../dist/cjs');
const client = dgram.createSocket('udp4');
const decoder = new Decoder();
@@ -23,18 +23,18 @@ setInterval(() => {
}
Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => {
const trackerName = decoder.trackers[trackerId]?.tracker_name?.tracker_name;
const trackerName = decoder.trackers[trackerId]?.name;
console.log(`Tracker - id: ${trackerId} | name: ${trackerName || ''}`);
if (tracker.pos) {
console.log(`\tpos: ${tracker.pos.pos_x}, ${tracker.pos.pos_y}, ${tracker.pos.pos_z}`);
console.log(`\tpos: ${tracker.pos.x}, ${tracker.pos.x}, ${tracker.pos.x}`);
}
if (tracker.speed) {
console.log(`\tspeed: ${tracker.speed.speed_x}, ${tracker.speed.speed_y}, ${tracker.speed.speed_z}`);
console.log(`\tspeed: ${tracker.speed.x}, ${tracker.speed.y}, ${tracker.speed.z}`);
}
if (tracker.ori) {
console.log(`\tori: ${tracker.ori.ori_x}, ${tracker.ori.ori_y}, ${tracker.ori.ori_z}`);
console.log(`\tori: ${tracker.ori.x}, ${tracker.ori.y}, ${tracker.ori.z}`);
}
if (tracker.status) {
@@ -42,17 +42,15 @@ setInterval(() => {
}
if (tracker.accel) {
console.log(`\taccel: ${tracker.accel.accel_x}, ${tracker.accel.accel_y}, ${tracker.accel.accel_z}`);
console.log(`\taccel: ${tracker.accel.x}, ${tracker.accel.y}, ${tracker.accel.z}`);
}
if (tracker.trgtpos) {
console.log(
`\ttrgtpos: ${tracker.trgtpos.trgtpos_x}, ${tracker.trgtpos.trgtpos_y}, ${tracker.trgtpos.trgtpos_z}`
);
console.log(`\ttrgtpos: ${tracker.trgtpos.x}, ${tracker.trgtpos.y}, ${tracker.trgtpos.z}`);
}
if (tracker.timestamp) {
console.log(`\ttimestamp: ${tracker.timestamp.tracker_timestamp}`);
console.log(`\ttimestamp: ${tracker.timestamp}`);
}
});
}, 1000);
+5 -13
View File
@@ -1,10 +1,9 @@
// recreation of psn_server.cpp example from https://github.com/vyv/psn-cpp
const dgram = require('dgram');
const { Encoder, Tracker, Decoder } = require('../dist');
const { Encoder, Tracker } = require('../dist/cjs');
const client = dgram.createSocket('udp4');
const encoder = new Encoder('Test PSN Server', 2, 0);
const decoder = new Decoder();
const trackers = [];
@@ -40,25 +39,18 @@ setInterval(() => {
trackers[index].setTimestamp(timestamp);
});
console.log(`Sending Data Packets`);
const dataPackets = encoder.getDataPackets(timestamp, trackers);
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}`
);
dataPackets.forEach((packet) => {
client.send(packet, 56565, '236.10.10.10');
});
timestamp += 1;
}, 5);
setInterval(() => {
console.log(`Sending Info Packets`);
const infoPackets = encoder.getInfoPackets(timestamp, trackers);
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}`
);
infoPackets.forEach((packet) => {
client.send(packet, 56565, '236.10.10.10');
});
}, 500);
+3463 -19
View File
File diff suppressed because it is too large Load Diff
+26 -9
View File
@@ -1,15 +1,29 @@
{
"name": "@jwetzell/posistagenet",
"version": "0.4.7",
"version": "2.0.0",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"types": "./dist/types/index.d.ts"
}
},
"scripts": {
"prebuild": "rimraf dist",
"build": "tsc",
"build": "npm run build:cjs && npm run build:esm && npm run build:types",
"build:cjs": "tsc -p tsconfig.cjs.json",
"build:esm": "tsc -p tsconfig.esm.json",
"build:types": "tsc -p tsconfig.types.json",
"example:client": "node examples/psn_client.js",
"example:server": "node examples/psn_server.js",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build",
"lint:check": "eslint ./",
"format:check": "prettier ./ --check",
"format:write": "prettier ./ --write"
},
"files": [
"dist"
@@ -20,11 +34,14 @@
"url": "https://jwetzell.com"
},
"repository": "https://github.com/jwetzell/psn-js",
"license": "ISC",
"license": "MIT",
"devDependencies": {
"@types/node": "22.7.4",
"prettier": "3.3.3",
"@types/node": "22.10.2",
"prettier": "3.4.2",
"rimraf": "6.0.1",
"typescript": "5.6.2"
"typescript": "5.7.2",
"eslint": "8.48.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "9.0.0"
}
}
+51 -69
View File
@@ -1,33 +1,32 @@
import { Decoders } from '.';
import { DataPacketChunk, InfoPacketChunk, InfoTrackerChunk, PacketHeaderChunk } from './models';
import { DataPacketChunk, InfoPacketChunk, Tracker, TrackerFromData, TrackerFromInfo } from './models';
export class Decoder {
// TODO(jwetzell): check if these last packet headers are necessary to hold on to
lastInfoPacketHeader?: PacketHeaderChunk;
lastDataPacketHeader?: PacketHeaderChunk;
infoPacketFrames: { [key: number]: InfoPacketChunk[] } = {};
dataPacketFrames: { [key: number]: DataPacketChunk[] } = {};
trackers: { [key: string]: InfoTrackerChunk } = {};
trackers: { [key: string]: Tracker } = {};
system_name: string = '';
systemName: string = '';
constructor() {}
updateInfo(framePackets: InfoPacketChunk[]) {
framePackets.forEach((packet) => {
if (packet.system_name) {
this.system_name = packet.system_name.system_name;
if (packet.data.systemName?.data) {
this.systemName = packet.data.systemName?.data.systemName;
}
if (packet.tracker_list?.trackers) {
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
if (!this.trackers[trackerId]) {
this.trackers[trackerId] = {};
if (packet.data.trackerList?.data) {
packet.data.trackerList.data.trackers.forEach((infoTrackerChunk) => {
if (!this.trackers[infoTrackerChunk.chunk.header.id]) {
const tracker = TrackerFromInfo(infoTrackerChunk);
if (tracker) {
this.trackers[infoTrackerChunk.chunk.header.id] = tracker;
}
}
this.trackers[trackerId].tracker_name = tracker.tracker_name;
const tracker = this.trackers[infoTrackerChunk.chunk.header.id];
tracker.updateInfo(infoTrackerChunk);
});
}
});
@@ -35,97 +34,80 @@ export class Decoder {
updateData(framePackets: DataPacketChunk[]) {
framePackets.forEach((packet) => {
if (packet.tracker_list) {
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
this.trackers[trackerId] = {
...this.trackers[trackerId],
...tracker,
};
if (packet.data.trackerList) {
packet.data.trackerList?.data.trackers.forEach((dataTrackerChunk) => {
if (!this.trackers[dataTrackerChunk.chunk.header.id]) {
const tracker = TrackerFromData(dataTrackerChunk);
if (tracker) {
this.trackers[dataTrackerChunk.chunk.header.id] = tracker;
}
}
const tracker = this.trackers[dataTrackerChunk.chunk.header.id];
tracker.updateData(dataTrackerChunk);
});
}
});
}
// TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete
decode(packetBuf: Buffer): DataPacketChunk | InfoPacketChunk | undefined {
const packet = Decoders.Packet(packetBuf);
decode(packetBuf: Uint8Array) {
const packet = Decoders.Chunk(packetBuf);
if (packet === undefined) {
return packet;
}
if (packet.id === 0x6756) {
const infoPacket = packet as InfoPacketChunk;
if (infoPacket && infoPacket.has_subchunks) {
const currentInfoPacketHeader = infoPacket.packet_header;
if (packet.header.id === 0x6756) {
const infoPacket = Decoders.InfoPacketChunk(packetBuf);
if (infoPacket && infoPacket.chunk.header.hasSubchunks) {
const currentInfoPacketHeader = infoPacket.data.packetHeader;
if (!currentInfoPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet');
}
const systemSubChunk = infoPacket.system_name;
const systemSubChunk = infoPacket.data.systemName;
if (!systemSubChunk) {
// NOTE(jwetzell): not sure that info packets without a system subchunk are valid?
throw new Error('malformed packet');
}
if (currentInfoPacketHeader.frame_id) {
if (this.infoPacketFrames[currentInfoPacketHeader.frame_id] === undefined) {
this.infoPacketFrames[currentInfoPacketHeader.frame_id] = [];
if (currentInfoPacketHeader.data.frameId) {
if (this.infoPacketFrames[currentInfoPacketHeader.data.frameId] === undefined) {
this.infoPacketFrames[currentInfoPacketHeader.data.frameId] = [];
}
this.infoPacketFrames[currentInfoPacketHeader.frame_id].push(infoPacket);
this.infoPacketFrames[currentInfoPacketHeader.data.frameId].push(infoPacket);
if (
this.infoPacketFrames[currentInfoPacketHeader.frame_id].length ===
currentInfoPacketHeader.frame_packet_count
this.infoPacketFrames[currentInfoPacketHeader.data.frameId].length ===
currentInfoPacketHeader.data.framePacketCount
) {
this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.frame_id]);
delete this.infoPacketFrames[currentInfoPacketHeader.frame_id];
this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.data.frameId]);
delete this.infoPacketFrames[currentInfoPacketHeader.data.frameId];
}
}
this.lastInfoPacketHeader = currentInfoPacketHeader;
}
} else if (packet.id === 0x6755) {
const dataPacket = packet as DataPacketChunk;
if (dataPacket.has_subchunks) {
const currentDataPacketHeader = dataPacket.packet_header;
} else if (packet.header.id === 0x6755) {
const dataPacket = Decoders.DataPacketChunk(packetBuf);
if (dataPacket.chunk.header.hasSubchunks) {
const currentDataPacketHeader = dataPacket.data.packetHeader;
if (!currentDataPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet');
}
if (currentDataPacketHeader.frame_id) {
if (this.dataPacketFrames[currentDataPacketHeader.frame_id] === undefined) {
this.dataPacketFrames[currentDataPacketHeader.frame_id] = [];
if (currentDataPacketHeader.data.frameId) {
if (this.dataPacketFrames[currentDataPacketHeader.data.frameId] === undefined) {
this.dataPacketFrames[currentDataPacketHeader.data.frameId] = [];
}
this.dataPacketFrames[currentDataPacketHeader.frame_id].push(dataPacket);
this.dataPacketFrames[currentDataPacketHeader.data.frameId].push(dataPacket);
if (
this.dataPacketFrames[currentDataPacketHeader.frame_id].length ===
currentDataPacketHeader.frame_packet_count
this.dataPacketFrames[currentDataPacketHeader.data.frameId].length ===
currentDataPacketHeader.data.framePacketCount
) {
this.updateData(this.dataPacketFrames[currentDataPacketHeader.frame_id]);
delete this.dataPacketFrames[currentDataPacketHeader.frame_id];
this.updateData(this.dataPacketFrames[currentDataPacketHeader.data.frameId]);
delete this.dataPacketFrames[currentDataPacketHeader.data.frameId];
}
}
this.lastDataPacketHeader = currentDataPacketHeader;
}
}
return packet;
}
// NOTE(jwetzell): gets merged set of tracker field keys minus the guaranteed properties
getTrackerFields(): Set<string> {
const keys = new Set(
Object.values(this.trackers)
.map((tracker) => Object.keys(tracker))
.flat(1)
);
// NOTE(jwetzell): remove fields that definitely exist
keys.delete('id');
keys.delete('has_subchunks');
keys.delete('data_len');
keys.delete('chunk_data');
return keys;
}
}
+19 -8
View File
@@ -1,18 +1,29 @@
import { Chunk } from '../models/chunk';
export default (buffer: Buffer, dataDecoder: Function): Chunk => {
export default (buffer: Uint8Array): Chunk => {
let offset = 0;
const chunk: Chunk = {};
chunk.id = buffer.readUInt16LE(offset);
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const id = view.getUint16(offset, true);
offset += 2;
// 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;
const combinedLengthAndFlag = view.getUint16(offset, true);
const hasSubchunks = combinedLengthAndFlag > 32768;
const dataLen = hasSubchunks ? combinedLengthAndFlag - 32768 : combinedLengthAndFlag;
offset += 2;
chunk.chunk_data = buffer.subarray(offset, offset + chunk.data_len);
dataDecoder(chunk);
const header = {
id,
dataLen,
hasSubchunks,
};
const chunkData = buffer.subarray(offset, offset + header.dataLen);
const chunk = {
chunkData,
header,
};
return chunk;
};
+21 -13
View File
@@ -1,25 +1,30 @@
import { Decoders } from '..';
import { Constants } from '../../constants';
import { DataPacketChunk } from '../../models/data/data-packet-chunk';
import { DataPacketChunk, DataPacketChunkData } from '../../models/data/data-packet-chunk';
function decodeDataPacketChunk(dataPacketChunk: DataPacketChunk) {
if (dataPacketChunk.has_subchunks && dataPacketChunk.chunk_data && dataPacketChunk.data_len) {
export default (buffer: Uint8Array): DataPacketChunk => {
const chunk = Decoders.Chunk(buffer);
const data: DataPacketChunkData = {};
if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) {
let offset = 0;
while (offset < dataPacketChunk.data_len) {
const chunkId = dataPacketChunk.chunk_data.readUInt16LE(offset);
while (offset < chunk.header.dataLen) {
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const chunkId = view.getUint16(offset, true);
switch (chunkId) {
case 0x0000:
dataPacketChunk.packet_header = Decoders.PacketHeaderChunk(dataPacketChunk.chunk_data.subarray(offset));
data.packetHeader = Decoders.PacketHeaderChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (dataPacketChunk.packet_header?.data_len) {
offset += dataPacketChunk.packet_header.data_len;
if (data.packetHeader.chunk.header.dataLen) {
offset += data.packetHeader.chunk.header.dataLen;
}
break;
case 0x0001:
dataPacketChunk.tracker_list = Decoders.DataTrackerListChunk(dataPacketChunk.chunk_data.subarray(offset));
data.trackerList = Decoders.DataTrackerListChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (dataPacketChunk.tracker_list.data_len) {
offset += dataPacketChunk.tracker_list.data_len;
if (data.trackerList.chunk.header.dataLen) {
offset += data.trackerList.chunk.header.dataLen;
}
break;
default:
@@ -27,6 +32,9 @@ function decodeDataPacketChunk(dataPacketChunk: DataPacketChunk) {
}
}
}
}
export default (buffer: Buffer): DataPacketChunk => Decoders.Chunk(buffer, decodeDataPacketChunk) as DataPacketChunk;
return {
chunk,
data,
};
};
+38 -35
View File
@@ -1,43 +1,46 @@
import { Decoders } from '..';
import { Constants } from '../../constants';
import { DataTrackerChunk } from '../../models/data/data-tracker-chunk';
import { DataTrackerChunk, DataTrackerChunkData } from '../../models/data/data-tracker-chunk';
function decodeTrackerChunk(trackerChunk: DataTrackerChunk) {
if (trackerChunk.chunk_data && trackerChunk.data_len) {
export default (buffer: Uint8Array): DataTrackerChunk => {
const chunk = Decoders.Chunk(buffer);
const data: DataTrackerChunkData = {};
if (chunk.chunkData && chunk.header.dataLen) {
let offset = 0;
while (offset < trackerChunk.data_len) {
const trackerFieldChunk = Decoders.DataTrackerFieldChunk(trackerChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (trackerFieldChunk.data_len) {
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;
}
while (offset < chunk.header.dataLen) {
const trackerFieldChunk = Decoders.Chunk(chunk.chunkData.subarray(offset));
switch (trackerFieldChunk.header.id) {
case 0x0000:
data.pos = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
break;
case 0x0001:
data.speed = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
break;
case 0x0002:
data.ori = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
break;
case 0x0003:
data.status = Decoders.DataTrackerStatusChunk(chunk.chunkData.subarray(offset));
break;
case 0x0004:
data.accel = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
break;
case 0x0005:
data.trgtpos = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
break;
case 0x0006:
data.timestamp = Decoders.DataTrackerTimestampChunk(chunk.chunkData.subarray(offset));
break;
default:
break;
}
offset += Constants.CHUNK_HEADER_SIZE;
offset += trackerFieldChunk.header.dataLen;
}
}
}
export default (buffer: Buffer): DataTrackerChunk => Decoders.Chunk(buffer, decodeTrackerChunk) as DataTrackerChunk;
return {
chunk,
data,
};
};
@@ -1,48 +0,0 @@
/* eslint-disable no-case-declarations */
import { Decoders } from '..';
import { DataTrackerFieldChunk } from '../../models/data/data-tracker-field-chunk';
function readXYZ(trackerFieldChunk: DataTrackerFieldChunk, prefix: string = '') {
if (trackerFieldChunk.chunk_data) {
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: DataTrackerFieldChunk) {
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:
if (trackerFieldChunk.chunk_data) {
trackerFieldChunk.validity = trackerFieldChunk.chunk_data.readFloatLE();
}
break;
case 0x0004:
readXYZ(trackerFieldChunk, 'accel_');
break;
case 0x0005:
readXYZ(trackerFieldChunk, 'trgtpos_');
break;
case 0x0006:
if (trackerFieldChunk.chunk_data) {
trackerFieldChunk.tracker_timestamp = trackerFieldChunk.chunk_data.readBigUInt64LE();
}
break;
default:
break;
}
}
}
export default (buffer: Buffer): DataTrackerFieldChunk =>
Decoders.Chunk(buffer, decodeTrackerFieldChunk) as DataTrackerFieldChunk;
+23 -14
View File
@@ -1,24 +1,33 @@
import { Decoders } from '..';
import { Constants } from '../../constants';
import { DataTrackerListChunk } from '../../models/data/data-tracker-list-chunk';
import { DataTrackerChunk } from '../../models';
import { DataTrackerListChunk, DataTrackerListChunkData } from '../../models/data/data-tracker-list-chunk';
function decodeDataTrackerListChunk(dataTrackerListChunk: DataTrackerListChunk) {
dataTrackerListChunk.trackers = {};
export default (buffer: Uint8Array): DataTrackerListChunk => {
const chunk = Decoders.Chunk(buffer);
const trackers: DataTrackerChunk[] = [];
// TODO(jwetzell): add error handling
let offset = 0;
if (dataTrackerListChunk.chunk_data) {
while (offset < dataTrackerListChunk.chunk_data.length) {
const trackerChunk = Decoders.DataTrackerChunk(dataTrackerListChunk.chunk_data.subarray(offset));
if (chunk.chunkData) {
let offset = 0;
while (offset < chunk.chunkData.length) {
const trackerChunk = Decoders.DataTrackerChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (trackerChunk.data_len) {
offset += trackerChunk.data_len;
if (trackerChunk.chunk.header.dataLen) {
offset += trackerChunk.chunk.header.dataLen;
}
if (trackerChunk.id !== undefined) {
dataTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
if (trackerChunk.chunk.header.id !== undefined) {
trackers.push(trackerChunk);
}
}
}
}
export default (buffer: Buffer): DataTrackerListChunk =>
Decoders.Chunk(buffer, decodeDataTrackerListChunk) as DataTrackerListChunk;
const data: DataTrackerListChunkData = {
trackers,
};
return {
chunk,
data,
};
};
@@ -0,0 +1,20 @@
/* eslint-disable no-case-declarations */
import { Decoders } from '..';
import { DataTrackerStatusChunk, DataTrackerStatusChunkData } from '../../models/data/data-tracker-status-chunk';
export default (buffer: Uint8Array): DataTrackerStatusChunk => {
const chunk = Decoders.Chunk(buffer);
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const validity = view.getFloat32(0, true);
const data: DataTrackerStatusChunkData = {
validity,
};
return {
chunk,
data,
};
};
@@ -0,0 +1,23 @@
/* eslint-disable no-case-declarations */
import { Decoders } from '..';
import {
DataTrackerTimestampChunk,
DataTrackerTimestampChunkData,
} from '../../models/data/data-tracker-timestamp-chunk';
export default (buffer: Uint8Array): DataTrackerTimestampChunk => {
const chunk = Decoders.Chunk(buffer);
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const timestamp = view.getBigUint64(0, true);
const data: DataTrackerTimestampChunkData = {
timestamp,
};
return {
chunk,
data,
};
};
@@ -0,0 +1,20 @@
import { Decoders } from '..';
import { DataTrackerXYZChunk, DataTrackerXYZChunkData } from '../../models/data/data-tracker-xyz-chunk';
export default (buffer: Uint8Array): DataTrackerXYZChunk => {
const chunk = Decoders.Chunk(buffer);
// TODO(jwetzell): add error handling
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const data: DataTrackerXYZChunkData = {
x: view.getFloat32(0, true),
y: view.getFloat32(4, true),
z: view.getFloat32(8, true),
};
return {
chunk,
data,
};
};
+6 -2
View File
@@ -4,8 +4,10 @@ import PacketHeaderChunk from './packet-header-chunk';
import DataPacketChunk from './data/data-packet-chunk';
import DataTrackerChunk from './data/data-tracker-chunk';
import DataTrackerFieldChunk from './data/data-tracker-field-chunk';
import DataTrackerListChunk from './data/data-tracker-list-chunk';
import DataTrackerStatusChunk from './data/data-tracker-status-chunk';
import DataTrackerTimestampChunk from './data/data-tracker-timestamp-chunk';
import DataTrackerXYZChunk from './data/data-tracker-xyz-chunk';
import InfoPacketChunk from './info/info-packet-chunk';
import InfoSystemNameChunk from './info/info-system-name-chunk';
@@ -19,7 +21,9 @@ export const Decoders = {
Packet,
DataPacketChunk,
DataTrackerChunk,
DataTrackerFieldChunk,
DataTrackerXYZChunk,
DataTrackerStatusChunk,
DataTrackerTimestampChunk,
DataTrackerListChunk,
InfoPacketChunk,
InfoSystemNameChunk,
+24 -16
View File
@@ -1,32 +1,37 @@
import { Decoders } from '..';
import { Constants } from '../../constants';
import { InfoPacketChunk } from '../../models/info/info-packet-chunk';
import { InfoPacketChunk, InfoPacketChunkData } from '../../models/info/info-packet-chunk';
function decodeInfoPacketChunk(infoPacketChunk: InfoPacketChunk) {
if (infoPacketChunk.has_subchunks && infoPacketChunk.chunk_data && infoPacketChunk.data_len) {
export default (buffer: Uint8Array): InfoPacketChunk => {
const chunk = Decoders.Chunk(buffer);
const data: InfoPacketChunkData = {};
if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) {
let offset = 0;
while (offset < infoPacketChunk.data_len) {
const chunkId = infoPacketChunk.chunk_data.readUInt16LE(offset);
while (offset < chunk.header.dataLen) {
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const chunkId = view.getUint16(offset, true);
switch (chunkId) {
case 0x0000:
infoPacketChunk.packet_header = Decoders.PacketHeaderChunk(infoPacketChunk.chunk_data.subarray(offset));
data.packetHeader = Decoders.PacketHeaderChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoPacketChunk.packet_header?.data_len) {
offset += infoPacketChunk.packet_header.data_len;
if (data.packetHeader?.chunk.header.dataLen) {
offset += data.packetHeader.chunk.header.dataLen;
}
break;
case 0x0001:
infoPacketChunk.system_name = Decoders.InfoSystemNameChunk(infoPacketChunk.chunk_data.subarray(offset));
data.systemName = Decoders.InfoSystemNameChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoPacketChunk.system_name?.data_len) {
offset += infoPacketChunk.system_name.data_len;
if (data.systemName?.chunk.header.dataLen) {
offset += data.systemName?.chunk.header.dataLen;
}
break;
case 0x0002:
infoPacketChunk.tracker_list = Decoders.InfoTrackerListChunk(infoPacketChunk.chunk_data.subarray(offset));
data.trackerList = Decoders.InfoTrackerListChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoPacketChunk.tracker_list?.data_len) {
offset += infoPacketChunk.tracker_list.data_len;
if (data.trackerList?.chunk.header.dataLen) {
offset += data.trackerList.chunk.header.dataLen;
}
break;
default:
@@ -34,6 +39,9 @@ function decodeInfoPacketChunk(infoPacketChunk: InfoPacketChunk) {
}
}
}
}
export default (buffer: Buffer): InfoPacketChunk => Decoders.Chunk(buffer, decodeInfoPacketChunk) as InfoPacketChunk;
return {
chunk,
data,
};
};
+12 -8
View File
@@ -1,11 +1,15 @@
import { Decoders } from '..';
import { InfoSystemNameChunk } from '../../models/info/info-system-name-chunk';
import { InfoSystemNameChunk, InfoSystemNameChunkData } from '../../models/info/info-system-name-chunk';
function decodeSystemNameChunk(systemNameChunk: InfoSystemNameChunk) {
if (systemNameChunk.chunk_data !== undefined && systemNameChunk.data_len !== undefined) {
systemNameChunk.system_name = systemNameChunk.chunk_data.subarray(0, systemNameChunk.data_len).toString();
}
}
export default (buffer: Uint8Array): InfoSystemNameChunk => {
const chunk = Decoders.Chunk(buffer);
export default (buffer: Buffer): InfoSystemNameChunk =>
Decoders.Chunk(buffer, decodeSystemNameChunk) as InfoSystemNameChunk;
const data: InfoSystemNameChunkData = {
systemName: new TextDecoder().decode(chunk.chunkData.subarray(0, chunk.header.dataLen)),
};
return {
chunk,
data,
};
};
+21 -11
View File
@@ -1,26 +1,36 @@
import { Decoders } from '..';
import { Constants } from '../../constants';
import { InfoTrackerChunk } from '../../models/info/info-tracker-chunk';
import { InfoTrackerChunk, InfoTrackerChunkData } from '../../models/info/info-tracker-chunk';
function decodeInfoTrackerChunk(infoTrackerChunk: InfoTrackerChunk) {
if (infoTrackerChunk.has_subchunks && infoTrackerChunk.chunk_data && infoTrackerChunk.data_len) {
export default (buffer: Uint8Array): InfoTrackerChunk => {
const chunk = Decoders.Chunk(buffer);
if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) {
let offset = 0;
while (offset < infoTrackerChunk.data_len) {
const chunkId = infoTrackerChunk.chunk_data.readUInt16LE(offset);
while (offset < chunk.header.dataLen) {
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const chunkId = view.getUint16(offset, true);
switch (chunkId) {
case 0x0000:
infoTrackerChunk.tracker_name = Decoders.InfoTrackerNameChunk(infoTrackerChunk.chunk_data.subarray(offset));
const data: InfoTrackerChunkData = {
trackerName: Decoders.InfoTrackerNameChunk(chunk.chunkData.subarray(offset)),
};
offset += Constants.CHUNK_HEADER_SIZE;
if (infoTrackerChunk.tracker_name?.data_len) {
offset += infoTrackerChunk?.tracker_name?.data_len;
if (data.trackerName.chunk.header.dataLen) {
offset += data.trackerName.chunk.header.dataLen;
}
break;
return {
chunk,
data,
};
default:
break;
}
}
}
}
export default (buffer: Buffer): InfoTrackerChunk => Decoders.Chunk(buffer, decodeInfoTrackerChunk);
return {
chunk,
};
};
+23 -14
View File
@@ -1,24 +1,33 @@
import { Decoders } from '..';
import { Constants } from '../../constants';
import { InfoTrackerListChunk } from '../../models/info/info-tracker-list-chunk';
import { InfoTrackerChunk } from '../../models/info/info-tracker-chunk';
import { InfoTrackerListChunk, InfoTrackerListChunkData } from '../../models/info/info-tracker-list-chunk';
function decodeInfoTrackerListChunk(infoTrackerListChunk: InfoTrackerListChunk) {
infoTrackerListChunk.trackers = {};
if (infoTrackerListChunk.has_subchunks && infoTrackerListChunk.chunk_data) {
export default (buffer: Uint8Array): InfoTrackerListChunk => {
const chunk = Decoders.Chunk(buffer);
const trackers: InfoTrackerChunk[] = [];
if (chunk.header.hasSubchunks && chunk.chunkData) {
let offset = 0;
if (infoTrackerListChunk.data_len) {
while (offset < infoTrackerListChunk.data_len) {
const trackerChunk = Decoders.InfoTrackerChunk(infoTrackerListChunk.chunk_data.subarray(offset));
if (chunk.header.dataLen) {
while (offset < chunk.header.dataLen) {
const trackerChunk = Decoders.InfoTrackerChunk(chunk.chunkData.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (trackerChunk.data_len) {
offset += trackerChunk.data_len;
if (trackerChunk.chunk.header.dataLen) {
offset += trackerChunk.chunk.header.dataLen;
}
if (trackerChunk.id !== undefined) {
infoTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
if (trackerChunk.chunk.header.id !== undefined) {
trackers.push(trackerChunk);
}
}
}
}
}
export default (buffer: Buffer): InfoTrackerListChunk =>
Decoders.Chunk(buffer, decodeInfoTrackerListChunk) as InfoTrackerListChunk;
const data: InfoTrackerListChunkData = {
trackers,
};
return {
chunk,
data,
};
};
+13 -8
View File
@@ -1,10 +1,15 @@
import { Decoders } from '..';
import { InfoTrackerNameChunk } from '../../models/info/info-tracker-name-chunk';
import { InfoTrackerNameChunk, InfoTrackerNameChunkData } from '../../models/info/info-tracker-name-chunk';
function decodeTrackerNameChunk(trackerNameChunk: InfoTrackerNameChunk) {
if (trackerNameChunk.chunk_data !== undefined && trackerNameChunk.data_len !== undefined) {
trackerNameChunk.tracker_name = trackerNameChunk.chunk_data.subarray(0, trackerNameChunk.data_len).toString();
}
}
export default (buffer: Buffer): InfoTrackerNameChunk =>
Decoders.Chunk(buffer, decodeTrackerNameChunk) as InfoTrackerNameChunk;
export default (buffer: Uint8Array): InfoTrackerNameChunk => {
const chunk = Decoders.Chunk(buffer);
const data: InfoTrackerNameChunkData = {
trackerName: new TextDecoder().decode(chunk.chunkData.subarray(0, chunk.header.dataLen)),
};
return {
chunk,
data,
};
};
+17 -11
View File
@@ -1,14 +1,20 @@
import { Decoders } from '.';
import { PacketHeaderChunk } from '../models/packet-header-chunk';
import { PacketHeaderChunk, PacketHeaderChunkData } from '../models/packet-header-chunk';
function decodePacketHeaderChunk(packetHeaderChunk: PacketHeaderChunk) {
if (packetHeaderChunk.chunk_data) {
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);
}
}
export default (buffer: Uint8Array): PacketHeaderChunk => {
const chunk = Decoders.Chunk(buffer);
export default (buffer: Buffer): PacketHeaderChunk => Decoders.Chunk(buffer, decodePacketHeaderChunk);
const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
const data: PacketHeaderChunkData = {
packetTimestamp: view.getBigUint64(0, true),
versionHigh: chunk.chunkData[8],
versionLow: chunk.chunkData[9],
frameId: chunk.chunkData[10],
framePacketCount: chunk.chunkData[11],
};
return {
chunk,
data,
};
};
+4 -2
View File
@@ -2,8 +2,10 @@ import { Decoders } from '.';
import { DataPacketChunk } from '../models/data/data-packet-chunk';
import { InfoPacketChunk } from '../models/info/info-packet-chunk';
export default (buffer: Buffer): InfoPacketChunk | DataPacketChunk | undefined => {
const chunkId = buffer.readUInt16LE();
export default (buffer: Uint8Array): InfoPacketChunk | DataPacketChunk | undefined => {
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const chunkId = view.getUint16(0, true);
switch (chunkId) {
case 0x6756:
return Decoders.InfoPacketChunk(buffer);
+7 -7
View File
@@ -47,14 +47,14 @@ export class Encoder {
const trackerChunks = trackers.map((tracker: Tracker) => tracker.getInfoChunk());
const infoPackets: Buffer[] = [];
const infoPackets: Uint8Array[] = [];
const trackerChunksLists: Buffer[][] = [];
let currentTrackerList: Buffer[] = [];
const trackerChunksLists: Uint8Array[][] = [];
let currentTrackerList: Uint8Array[] = [];
let currentInfoPacketSize = Constants.PACKET_HEADER_SIZE + systemNameChunk.length + Constants.CHUNK_HEADER_SIZE;
trackerChunks.forEach((trackerChunk: Buffer) => {
trackerChunks.forEach((trackerChunk: Uint8Array) => {
if (currentInfoPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
trackerChunksLists.push(currentTrackerList);
currentTrackerList = [];
@@ -95,10 +95,10 @@ export class Encoder {
}
const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk());
const dataPackets: Buffer[] = [];
const dataPackets: Uint8Array[] = [];
const trackerChunksLists: Buffer[][] = [];
let currentTrackerList: Buffer[] = [];
const trackerChunksLists: Uint8Array[][] = [];
let currentTrackerList: Uint8Array[] = [];
let currentDataPacketSize = Constants.PACKET_HEADER_SIZE + Constants.CHUNK_HEADER_SIZE;
+10 -5
View File
@@ -1,4 +1,4 @@
export default (id: number, chunkData: Buffer, hasSubchunks: boolean): Buffer => {
export default (id: number, chunkData: Uint8Array, hasSubchunks: boolean): Uint8Array => {
if (!Number.isInteger(id)) {
throw new Error('chunk id must be an integer');
}
@@ -11,10 +11,15 @@ export default (id: number, chunkData: Buffer, hasSubchunks: boolean): Buffer =>
throw new Error('chunkData can not be greater than 32767 bytes');
}
const header = Buffer.alloc(4);
header.writeUInt16LE(id);
const header = new DataView(new ArrayBuffer(4));
header.setUint16(0, id, true);
const hasSubChunksBit = (hasSubchunks ? 1 : 0) << 15;
header.writeUInt16LE(hasSubChunksBit + chunkData.length, 2);
header.setUint16(2, hasSubChunksBit + chunkData.length, true);
return Buffer.concat([header, chunkData]);
const headerBytes = new Uint8Array(header.buffer);
const bytes = new Uint8Array(headerBytes.length + chunkData.length);
bytes.set(headerBytes);
bytes.set(chunkData, headerBytes.length);
return bytes;
};
+6 -2
View File
@@ -1,3 +1,7 @@
import chunk from '../chunk';
export default (packetHeaderChunk: Buffer, trackerListChunk: Buffer): Buffer =>
chunk(0x6755, Buffer.concat([packetHeaderChunk, trackerListChunk]), true);
export default (packetHeaderChunk: Uint8Array, trackerListChunk: Uint8Array): Uint8Array => {
const chunkData = new Uint8Array(packetHeaderChunk.length + trackerListChunk.length);
chunkData.set(packetHeaderChunk);
chunkData.set(trackerListChunk, packetHeaderChunk.length);
return chunk(0x6755, chunkData, true);
};
@@ -1,9 +1,9 @@
import chunk from '../chunk';
export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12);
buf.writeFloatLE(x);
buf.writeFloatLE(y, 4);
buf.writeFloatLE(z, 8);
return chunk(0x0004, buf, false);
export default (x: number, y: number, z: number): Uint8Array => {
const buf = new DataView(new ArrayBuffer(12));
buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0004, new Uint8Array(buf.buffer), false);
};
+18 -2
View File
@@ -1,4 +1,20 @@
import chunk from '../chunk';
export default (trackerId: number, fieldChunks: Buffer[]): Buffer =>
chunk(trackerId, Buffer.concat(fieldChunks), fieldChunks.length > 0);
export default (trackerId: number, fieldChunks: Uint8Array[]): Uint8Array => {
let fieldChunksTotalLength = 0;
fieldChunks.forEach((fieldChunk) => {
fieldChunksTotalLength += fieldChunk.length;
});
const fieldChunksBytes = new Uint8Array(fieldChunksTotalLength);
let offset = 0;
fieldChunks.forEach((fieldChunk) => {
fieldChunksBytes.set(fieldChunk, offset);
offset += fieldChunk.length;
});
return chunk(trackerId, fieldChunksBytes, fieldChunks.length > 0);
};
+18 -1
View File
@@ -1,3 +1,20 @@
import chunk from '../chunk';
export default (trackerChunks: Buffer[]) => chunk(0x0001, Buffer.concat(trackerChunks), true);
export default (trackerChunks: Uint8Array[]) => {
let trackerChunksTotalLength = 0;
trackerChunks.forEach((trackerChunk) => {
trackerChunksTotalLength += trackerChunk.length;
});
const trackerChunksBytes = new Uint8Array(trackerChunksTotalLength);
let offset = 0;
trackerChunks.forEach((trackerChunk) => {
trackerChunksBytes.set(trackerChunk, offset);
offset += trackerChunk.length;
});
return chunk(0x0001, trackerChunksBytes, true);
};
+7 -6
View File
@@ -1,9 +1,10 @@
import chunk from '../chunk';
export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12);
buf.writeFloatLE(x);
buf.writeFloatLE(y, 4);
buf.writeFloatLE(z, 8);
return chunk(0x0002, buf, false);
export default (x: number, y: number, z: number): Uint8Array => {
const buf = new DataView(new ArrayBuffer(12));
buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0002, new Uint8Array(buf.buffer), false);
};
+8 -6
View File
@@ -1,9 +1,11 @@
import chunk from '../chunk';
export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12);
buf.writeFloatLE(x);
buf.writeFloatLE(y, 4);
buf.writeFloatLE(z, 8);
return chunk(0x0000, buf, false);
export default (x: number, y: number, z: number): Uint8Array => {
const buf = new DataView(new ArrayBuffer(12));
buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0000, new Uint8Array(buf.buffer), false);
};
@@ -1,9 +1,11 @@
import chunk from '../chunk';
export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12);
buf.writeFloatLE(x);
buf.writeFloatLE(y, 4);
buf.writeFloatLE(z, 8);
return chunk(0x0001, buf, false);
export default (x: number, y: number, z: number): Uint8Array => {
const buf = new DataView(new ArrayBuffer(12));
buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0001, new Uint8Array(buf.buffer), false);
};
@@ -1,7 +1,7 @@
import chunk from '../chunk';
export default (validity: number): Buffer => {
const buf = Buffer.alloc(4);
buf.writeFloatLE(validity);
return chunk(0x0003, buf, false);
export default (validity: number): Uint8Array => {
const buf = new DataView(new ArrayBuffer(4));
buf.setFloat32(0, validity, true);
return chunk(0x0003, new Uint8Array(buf.buffer), false);
};
@@ -1,7 +1,7 @@
import chunk from '../chunk';
export default (timestamp: bigint): Buffer => {
const buf = Buffer.alloc(8);
buf.writeBigUInt64LE(BigInt(timestamp));
return chunk(0x0006, buf, false);
export default (timestamp: bigint): Uint8Array => {
const buf = new DataView(new ArrayBuffer(8));
buf.setBigUint64(0, BigInt(timestamp), true);
return chunk(0x0006, new Uint8Array(buf.buffer), false);
};
@@ -1,9 +1,11 @@
import chunk from '../chunk';
export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12);
buf.writeFloatLE(x);
buf.writeFloatLE(y, 4);
buf.writeFloatLE(z, 8);
return chunk(0x0005, buf, false);
export default (x: number, y: number, z: number): Uint8Array => {
const buf = new DataView(new ArrayBuffer(12));
buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0005, new Uint8Array(buf.buffer), false);
};
+12 -2
View File
@@ -1,4 +1,14 @@
import chunk from '../chunk';
export default (packetHeaderChunk: Buffer, systemNameChunk: Buffer, trackerListChunk: Buffer): Buffer =>
chunk(0x6756, Buffer.concat([packetHeaderChunk, systemNameChunk, trackerListChunk]), true);
export default (
packetHeaderChunk: Uint8Array,
systemNameChunk: Uint8Array,
trackerListChunk: Uint8Array
): Uint8Array => {
const chunkData = new Uint8Array(packetHeaderChunk.length + systemNameChunk.length + trackerListChunk.length);
chunkData.set(packetHeaderChunk);
chunkData.set(systemNameChunk, packetHeaderChunk.length);
chunkData.set(trackerListChunk, packetHeaderChunk.length + systemNameChunk.length);
return chunk(0x6756, chunkData, true);
};
+1 -1
View File
@@ -1,3 +1,3 @@
import chunk from '../chunk';
export default (systemName: string): Buffer => chunk(0x0001, Buffer.from(systemName), false);
export default (systemName: string): Uint8Array => chunk(0x0001, new TextEncoder().encode(systemName), false);
+2 -1
View File
@@ -1,3 +1,4 @@
import chunk from '../chunk';
export default (trackerId: number, trackerNameChunk: Buffer): Buffer => chunk(trackerId, trackerNameChunk, true);
export default (trackerId: number, trackerNameChunk: Uint8Array): Uint8Array =>
chunk(trackerId, trackerNameChunk, true);
+17 -1
View File
@@ -1,3 +1,19 @@
import chunk from '../chunk';
export default (trackerChunks: Buffer[]): Buffer => chunk(0x0002, Buffer.concat(trackerChunks), true);
export default (trackerChunks: Uint8Array[]): Uint8Array => {
let trackerChunksTotalLength = 0;
trackerChunks.forEach((trackerChunk) => {
trackerChunksTotalLength += trackerChunk.length;
});
const trackerChunksBytes = new Uint8Array(trackerChunksTotalLength);
let offset = 0;
trackerChunks.forEach((trackerChunk) => {
trackerChunksBytes.set(trackerChunk, offset);
offset += trackerChunk.length;
});
return chunk(0x0002, trackerChunksBytes, true);
};
+1 -1
View File
@@ -1,3 +1,3 @@
import chunk from '../chunk';
export default (trackerName: string) => chunk(0x0000, Buffer.from(trackerName), false);
export default (trackerName: string) => chunk(0x0000, new TextEncoder().encode(trackerName), false);
+8 -8
View File
@@ -6,7 +6,7 @@ export default (
versionLow: number,
frameId: number,
framePacketCount: number
): Buffer => {
): Uint8Array => {
if (!Number.isInteger(versionHigh)) {
throw new Error('version high must be an integer');
}
@@ -33,12 +33,12 @@ export default (
throw new Error('frame packet count must be >= 0 and <= 255');
}
const packetHeader = Buffer.alloc(12);
packetHeader.writeBigUInt64LE(BigInt(timestamp));
packetHeader.writeUint8(versionHigh, 8);
packetHeader.writeUint8(versionLow, 9);
packetHeader.writeUint8(frameId, 10);
packetHeader.writeUint8(framePacketCount, 11);
const packetHeader = new DataView(new ArrayBuffer(12));
packetHeader.setBigUint64(0, BigInt(timestamp), true);
packetHeader.setUint8(8, versionHigh);
packetHeader.setUint8(9, versionLow);
packetHeader.setUint8(10, frameId);
packetHeader.setUint8(11, framePacketCount);
return chunk(0x0000, packetHeader, false);
return chunk(0x0000, new Uint8Array(packetHeader.buffer), false);
};
+9 -5
View File
@@ -1,6 +1,10 @@
export interface Chunk {
id?: number;
has_subchunks?: boolean;
data_len?: number;
chunk_data?: Buffer;
export interface ChunkHeader {
id: number;
dataLen: number;
hasSubchunks: boolean;
}
export interface Chunk {
chunkData: Uint8Array;
header: ChunkHeader;
}
+8 -3
View File
@@ -2,7 +2,12 @@ import { Chunk } from '../chunk';
import { PacketHeaderChunk } from '../packet-header-chunk';
import { DataTrackerListChunk } from './data-tracker-list-chunk';
export interface DataPacketChunk extends Chunk {
packet_header: PacketHeaderChunk;
tracker_list: DataTrackerListChunk;
export interface DataPacketChunkData {
packetHeader?: PacketHeaderChunk;
trackerList?: DataTrackerListChunk;
}
export interface DataPacketChunk {
chunk: Chunk;
data: DataPacketChunkData;
}
+16 -9
View File
@@ -1,12 +1,19 @@
import { Chunk } from '../chunk';
import { DataTrackerFieldChunk } from './data-tracker-field-chunk';
import { DataTrackerStatusChunk } from './data-tracker-status-chunk';
import { DataTrackerTimestampChunk } from './data-tracker-timestamp-chunk';
import { DataTrackerXYZChunk } from './data-tracker-xyz-chunk';
export interface DataTrackerChunk extends Chunk {
pos?: DataTrackerFieldChunk;
speed?: DataTrackerFieldChunk;
ori?: DataTrackerFieldChunk;
status?: DataTrackerFieldChunk;
accel?: DataTrackerFieldChunk;
trgtpos?: DataTrackerFieldChunk;
timestamp?: DataTrackerFieldChunk;
export interface DataTrackerChunkData {
pos?: DataTrackerXYZChunk;
speed?: DataTrackerXYZChunk;
ori?: DataTrackerXYZChunk;
status?: DataTrackerStatusChunk;
accel?: DataTrackerXYZChunk;
trgtpos?: DataTrackerXYZChunk;
timestamp?: DataTrackerTimestampChunk;
}
export interface DataTrackerChunk {
chunk: Chunk;
data: DataTrackerChunkData;
}
@@ -1,5 +0,0 @@
import { Chunk } from '../chunk';
export interface DataTrackerFieldChunk extends Chunk {
[key: string]: number | bigint | number[] | Buffer | undefined | boolean;
}
+7 -4
View File
@@ -1,8 +1,11 @@
import { Chunk } from '../chunk';
import { DataTrackerChunk } from './data-tracker-chunk';
export interface DataTrackerListChunk extends Chunk {
trackers: {
[key: number]: DataTrackerChunk;
};
export interface DataTrackerListChunkData {
trackers: DataTrackerChunk[];
}
export interface DataTrackerListChunk {
chunk: Chunk;
data: DataTrackerListChunkData;
}
@@ -0,0 +1,10 @@
import { Chunk } from '../chunk';
export interface DataTrackerStatusChunkData {
validity: number;
}
export interface DataTrackerStatusChunk {
chunk: Chunk;
data: DataTrackerStatusChunkData;
}
@@ -0,0 +1,10 @@
import { Chunk } from '../chunk';
export interface DataTrackerTimestampChunkData {
timestamp: bigint;
}
export interface DataTrackerTimestampChunk {
chunk: Chunk;
data: DataTrackerTimestampChunkData;
}
+12
View File
@@ -0,0 +1,12 @@
import { Chunk } from '../chunk';
export interface DataTrackerXYZChunkData {
x: number;
y: number;
z: number;
}
export interface DataTrackerXYZChunk {
chunk: Chunk;
data: DataTrackerXYZChunkData;
}
-1
View File
@@ -1,7 +1,6 @@
export * from './chunk';
export * from './data/data-packet-chunk';
export * from './data/data-tracker-chunk';
export * from './data/data-tracker-field-chunk';
export * from './data/data-tracker-list-chunk';
export * from './info/info-packet-chunk';
export * from './info/info-system-name-chunk';
+8 -4
View File
@@ -3,8 +3,12 @@ import { PacketHeaderChunk } from '../packet-header-chunk';
import { InfoSystemNameChunk } from './info-system-name-chunk';
import { InfoTrackerListChunk } from './info-tracker-list-chunk';
export interface InfoPacketChunk extends Chunk {
packet_header: PacketHeaderChunk;
system_name: InfoSystemNameChunk;
tracker_list: InfoTrackerListChunk;
export interface InfoPacketChunkData {
packetHeader?: PacketHeaderChunk;
systemName?: InfoSystemNameChunk;
trackerList?: InfoTrackerListChunk;
}
export interface InfoPacketChunk {
chunk: Chunk;
data: InfoPacketChunkData;
}
+7 -2
View File
@@ -1,5 +1,10 @@
import { Chunk } from '../chunk';
export interface InfoSystemNameChunk extends Chunk {
system_name: string;
export interface InfoSystemNameChunkData {
systemName: string;
}
export interface InfoSystemNameChunk {
chunk: Chunk;
data: InfoSystemNameChunkData;
}
+7 -2
View File
@@ -1,6 +1,11 @@
import { Chunk } from '../chunk';
import { InfoTrackerNameChunk } from './info-tracker-name-chunk';
export interface InfoTrackerChunk extends Chunk {
tracker_name?: InfoTrackerNameChunk;
export interface InfoTrackerChunkData {
trackerName: InfoTrackerNameChunk;
}
export interface InfoTrackerChunk {
chunk: Chunk;
data?: InfoTrackerChunkData;
}
+7 -4
View File
@@ -1,8 +1,11 @@
import { Chunk } from '../chunk';
import { InfoTrackerChunk } from './info-tracker-chunk';
export interface InfoTrackerListChunk extends Chunk {
trackers: {
[key: number]: InfoTrackerChunk;
};
export interface InfoTrackerListChunkData {
trackers: InfoTrackerChunk[];
}
export interface InfoTrackerListChunk {
chunk: Chunk;
data: InfoTrackerListChunkData;
}
+7 -2
View File
@@ -1,5 +1,10 @@
import { Chunk } from '../chunk';
export interface InfoTrackerNameChunk extends Chunk {
tracker_name: string;
export interface InfoTrackerNameChunkData {
trackerName: string;
}
export interface InfoTrackerNameChunk {
chunk: Chunk;
data: InfoTrackerNameChunkData;
}
+11 -6
View File
@@ -1,9 +1,14 @@
import { Chunk } from './chunk';
export interface PacketHeaderChunk extends Chunk {
packet_timestamp?: bigint;
version_high?: number;
version_low?: number;
frame_id?: number;
frame_packet_count?: number;
export interface PacketHeaderChunkData {
packetTimestamp: bigint;
versionHigh: number;
versionLow: number;
frameId: number;
framePacketCount: number;
}
export interface PacketHeaderChunk {
chunk: Chunk;
data: PacketHeaderChunkData;
}
+138 -16
View File
@@ -8,16 +8,24 @@ import dataTrackerTimestampChunk from '../encoders/data/data-tracker-timestamp-c
import dataTrackerTrgtposChunk from '../encoders/data/data-tracker-trgtpos-chunk';
import infoTrackerChunk from '../encoders/info/info-tracker-chunk';
import infoTrackerNameChunk from '../encoders/info/info-tracker-name-chunk';
import { DataTrackerChunk } from './data/data-tracker-chunk';
import { InfoTrackerChunk } from './info/info-tracker-chunk';
export type XYZData = {
x: number;
y: number;
z: number;
};
export class Tracker {
id: number;
name: string;
pos?: [number, number, number];
speed?: [number, number, number];
ori?: [number, number, number];
pos?: XYZData;
speed?: XYZData;
ori?: XYZData;
validity?: number;
accel?: [number, number, number];
trgtpos?: [number, number, number];
accel?: XYZData;
trgtpos?: XYZData;
timestamp?: bigint;
constructor(id: number, name: string) {
@@ -33,15 +41,45 @@ export class Tracker {
}
setPos(x: number, y: number, z: number) {
this.pos = [x, y, z];
if (this.pos === undefined) {
this.pos = {
x,
y,
z,
};
} else {
this.pos.x = x;
this.pos.y = y;
this.pos.z = z;
}
}
setSpeed(x: number, y: number, z: number) {
this.speed = [x, y, z];
if (this.speed === undefined) {
this.speed = {
x,
y,
z,
};
} else {
this.speed.x = x;
this.speed.y = y;
this.speed.z = z;
}
}
setOri(x: number, y: number, z: number) {
this.ori = [x, y, z];
if (this.ori === undefined) {
this.ori = {
x,
y,
z,
};
} else {
this.ori.x = x;
this.ori.y = y;
this.ori.z = z;
}
}
setStatus(validity: number) {
@@ -49,11 +87,31 @@ export class Tracker {
}
setAccel(x: number, y: number, z: number) {
this.accel = [x, y, z];
if (this.accel === undefined) {
this.accel = {
x,
y,
z,
};
} else {
this.accel.x = x;
this.accel.y = y;
this.accel.z = z;
}
}
setTrgtPos(x: number, y: number, z: number) {
this.trgtpos = [x, y, z];
if (this.trgtpos === undefined) {
this.trgtpos = {
x,
y,
z,
};
} else {
this.trgtpos.x = x;
this.trgtpos.y = y;
this.trgtpos.z = z;
}
}
setTimestamp(timestamp: bigint) {
@@ -61,18 +119,18 @@ export class Tracker {
}
getDataChunk() {
const fieldChunks: Buffer[] = [];
const fieldChunks: Uint8Array[] = [];
if (this.pos) {
fieldChunks.push(dataTrackerPosChunk(...this.pos));
fieldChunks.push(dataTrackerPosChunk(this.pos.x, this.pos.y, this.pos.z));
}
if (this.speed) {
fieldChunks.push(dataTrackerSpeedChunk(...this.speed));
fieldChunks.push(dataTrackerSpeedChunk(this.speed.x, this.speed.y, this.speed.z));
}
if (this.ori) {
fieldChunks.push(dataTrackerOriChunk(...this.ori));
fieldChunks.push(dataTrackerOriChunk(this.ori.x, this.ori.y, this.ori.z));
}
if (this.validity) {
@@ -80,11 +138,11 @@ export class Tracker {
}
if (this.accel) {
fieldChunks.push(dataTrackerAccelChunk(...this.accel));
fieldChunks.push(dataTrackerAccelChunk(this.accel.x, this.accel.y, this.accel.z));
}
if (this.trgtpos) {
fieldChunks.push(dataTrackerTrgtposChunk(...this.trgtpos));
fieldChunks.push(dataTrackerTrgtposChunk(this.trgtpos.x, this.trgtpos.y, this.trgtpos.z));
}
if (this.timestamp) {
@@ -97,4 +155,68 @@ export class Tracker {
getInfoChunk() {
return infoTrackerChunk(this.id, infoTrackerNameChunk(this.name));
}
updateInfo(infoTrackerChunk: InfoTrackerChunk) {
if (infoTrackerChunk.data) {
this.name = infoTrackerChunk.data.trackerName.data.trackerName;
}
}
updateData(dataTrackerChunk: DataTrackerChunk) {
if (dataTrackerChunk.data.pos) {
this.setPos(dataTrackerChunk.data.pos.data.x, dataTrackerChunk.data.pos.data.y, dataTrackerChunk.data.pos.data.z);
}
if (dataTrackerChunk.data.speed) {
this.setSpeed(
dataTrackerChunk.data.speed.data.x,
dataTrackerChunk.data.speed.data.y,
dataTrackerChunk.data.speed.data.z
);
}
if (dataTrackerChunk.data.ori) {
this.setOri(dataTrackerChunk.data.ori.data.x, dataTrackerChunk.data.ori.data.y, dataTrackerChunk.data.ori.data.z);
}
if (dataTrackerChunk.data.status) {
this.setStatus(dataTrackerChunk.data.status.data.validity);
}
if (dataTrackerChunk.data.accel) {
this.setAccel(
dataTrackerChunk.data.accel.data.x,
dataTrackerChunk.data.accel.data.y,
dataTrackerChunk.data.accel.data.z
);
}
if (dataTrackerChunk.data.trgtpos) {
this.setTrgtPos(
dataTrackerChunk.data.trgtpos.data.x,
dataTrackerChunk.data.trgtpos.data.y,
dataTrackerChunk.data.trgtpos.data.z
);
}
if (dataTrackerChunk.data.timestamp) {
this.setTimestamp(dataTrackerChunk.data.timestamp.data.timestamp);
}
}
}
export function TrackerFromInfo(infoTrackerChunk: InfoTrackerChunk) {
if (infoTrackerChunk.data) {
return new Tracker(infoTrackerChunk.chunk.header.id, infoTrackerChunk.data.trackerName.data.trackerName);
}
return undefined;
}
export function TrackerFromData(dataTrackerChunk: DataTrackerChunk) {
if (dataTrackerChunk.data) {
const tracker = new Tracker(dataTrackerChunk.chunk.header.id, '');
tracker.updateData(dataTrackerChunk);
return tracker;
}
return undefined;
}
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"declaration": false,
"outDir": "./dist/cjs"
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "ESNext",
"declaration": false,
"outDir": "./dist/esm"
}
}
+7 -7
View File
@@ -1,12 +1,12 @@
{
"compilerOptions": {
"moduleResolution": "Node",
"lib": ["ESNext"],
"target": "ESNext",
"esModuleInterop": true,
"module": "commonjs",
"target": "ES2020",
"declaration": true,
"rootDir": "./src",
"strict": true,
"outDir": "dist"
"isolatedModules": true,
"rootDir": "src/",
"strict": true
},
"exclude": ["node_modules", "dist", "examples"]
"include": ["src/"]
}
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "./dist/types"
}
}