1 Commits

Author SHA1 Message Date
jwetzell 6f6ebece34 2.0.0 2025-01-06 21:50:15 -06:00
78 changed files with 5274 additions and 4328 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'],
};
-3
View File
@@ -4,6 +4,3 @@ updates:
directory: '/' directory: '/'
schedule: schedule:
interval: 'weekly' interval: 'weekly'
ignore:
- dependency-name: "@types*"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
+1 -1
View File
@@ -4,7 +4,7 @@ on:
branches: branches:
- main - main
jobs: jobs:
build: build-webui:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out repository - name: Check out repository
+2
View File
@@ -22,3 +22,5 @@ jobs:
- name: Publish to NPM - name: Publish to NPM
run: npm publish --provenance --access=public run: npm publish --provenance --access=public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
-25
View File
@@ -1,25 +0,0 @@
name: Run @jwetzell/posistagenet tests
on:
pull_request:
branches:
- main
paths:
- 'src/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Set up Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.nvmrc'
cache: 'npm'
cache-dependency-path: './package-lock.json'
- name: Install Node.js dependencies
run: npm ci
- run: npm run test
+1 -1
View File
@@ -1 +1 @@
v24.15.0 v20.15.1
+2
View File
@@ -0,0 +1,2 @@
*.md
*.min.*
+8
View File
@@ -0,0 +1,8 @@
module.exports = {
trailingComma: 'es5',
tabWidth: 2,
semi: true,
singleQuote: true,
bracketSameLine: true,
printWidth: 120,
};
+1 -1
View File
@@ -1,3 +1,3 @@
{ {
"recommendations": ["esbenp.prettier-vscode"] "recommendations": ["esbenp.prettier-vscode"]
} }
+6 -4
View File
@@ -1,6 +1,8 @@
{ {
"editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": { "editor.formatOnSave": true,
"source.fixAll": "explicit" "editor.codeActionsOnSave": {
} "source.fixAll": "explicit",
"source.organizeImports": "explicit"
}
} }
+1 -1
View File
@@ -28,7 +28,7 @@ decoder.decode(infoPacketBuffer)
decoder.decode(dataPacketBuffer) decoder.decode(dataPacketBuffer)
// the system_name from info packets if available // the system_name from info packets if available
console.log(decoder.systemName) console.log(decoder.system_name)
// map of trackers populated with any data that has been received // map of trackers populated with any data that has been received
// this merges both info and data packet properties into one // this merges both info and data packet properties into one
+54 -54
View File
@@ -6,70 +6,70 @@ const encoder = new Encoder('test encoder', 2, 3);
const decoder = new Decoder(); const decoder = new Decoder();
function getNTrackers(n) { function getNTrackers(n) {
const trackers = []; const trackers = [];
for (let index = 0; index < n; index += 1) { for (let index = 0; index < n; index += 1) {
const tracker = new Tracker(index, `Tracker ${index}`); const tracker = new Tracker(index, `Tracker ${index}`);
tracker.setPos(0, 0, 0); tracker.setPos(0, 0, 0);
tracker.setSpeed(0, 0, 0); tracker.setSpeed(0, 0, 0);
tracker.setOri(0, 0, 0); tracker.setOri(0, 0, 0);
tracker.setAccel(0, 0, 0); tracker.setAccel(0, 0, 0);
tracker.setTrgtPos(0, 0, 0); tracker.setTrgtPos(0, 0, 0);
tracker.setStatus(1.0); tracker.setStatus(1.0);
tracker.setTimestamp(Date.now()); tracker.setTimestamp(Date.now());
trackers.push(tracker); trackers.push(tracker);
} }
return trackers; return trackers;
} }
function benchmark(trackerCount, iterations) { function benchmark(trackerCount, iterations) {
const benchmarkResults = { const benchmarkResults = {
data: {}, data: {},
info: {}, info: {},
}; };
const trackers = getNTrackers(trackerCount); const trackers = getNTrackers(trackerCount);
console.log( console.log(
`processing ${trackers.length} tracker${trackers.length > 1 ? 's' : ''} ${iterations} time${ `processing ${trackers.length} tracker${trackers.length > 1 ? 's' : ''} ${iterations} time${
iterations > 1 ? 's' : '' iterations > 1 ? 's' : ''
}` }`
); );
let latestEncodedPackets; let latestEncodedPackets;
// DATA // DATA
const dataEncoderStart = performance.now(); const dataEncoderStart = performance.now();
for (let index = 0; index < iterations; index += 1) { for (let index = 0; index < iterations; index += 1) {
latestEncodedPackets = encoder.getDataPackets(Date.now(), trackers); latestEncodedPackets = encoder.getDataPackets(Date.now(), trackers);
} }
benchmarkResults.data.encode = performance.now() - dataEncoderStart; benchmarkResults.data.encode = performance.now() - dataEncoderStart;
const dataDecodedStart = performance.now(); const dataDecodedStart = performance.now();
for (let index = 0; index < iterations; index += 1) { for (let index = 0; index < iterations; index += 1) {
latestEncodedPackets.forEach((packet) => { latestEncodedPackets.forEach((packet) => {
decoder.decode(packet); decoder.decode(packet);
}); });
} }
benchmarkResults.data.decode = performance.now() - dataDecodedStart; benchmarkResults.data.decode = performance.now() - dataDecodedStart;
// INFO // INFO
const infoEncoderStart = performance.now(); const infoEncoderStart = performance.now();
for (let index = 0; index < iterations; index += 1) { for (let index = 0; index < iterations; index += 1) {
latestEncodedPackets = encoder.getInfoPackets(Date.now(), trackers); latestEncodedPackets = encoder.getInfoPackets(Date.now(), trackers);
} }
benchmarkResults.info.encode = performance.now() - infoEncoderStart; benchmarkResults.info.encode = performance.now() - infoEncoderStart;
const infoDecodeStart = performance.now(); const infoDecodeStart = performance.now();
for (let index = 0; index < iterations; index += 1) { for (let index = 0; index < iterations; index += 1) {
latestEncodedPackets.forEach((packet) => { latestEncodedPackets.forEach((packet) => {
decoder.decode(packet); decoder.decode(packet);
}); });
} }
benchmarkResults.info.decode = performance.now() - infoDecodeStart; benchmarkResults.info.decode = performance.now() - infoDecodeStart;
console.log(benchmarkResults); console.log(benchmarkResults);
} }
testSizes.forEach((iterations) => { testSizes.forEach((iterations) => {
testSizes.forEach((trackerCount) => { testSizes.forEach((trackerCount) => {
benchmark(trackerCount, iterations); benchmark(trackerCount, iterations);
}); });
}); });
-35
View File
@@ -1,35 +0,0 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.3/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"linter": {
"enabled": true,
"rules": {
"preset": "recommended"
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"trailingCommas": "es5"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
+6 -9
View File
@@ -3,17 +3,14 @@ const { Decoder } = require('../dist/cjs');
const decoder = new Decoder(); const decoder = new Decoder();
const infoPacketBuffer = new Uint8Array([ const infoPacketBuffer = new Uint8Array([
0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x56, 0x67, 0x34, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x01, 0x01, 0x00, 0x0b, 0x00, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11,
0x72, 0x76, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x02, 0x00, 0x11, 0x80, 0x80, 0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31,
0x01, 0x00, 0x0d, 0x80, 0x00, 0x00, 0x09, 0x00, 0x54, 0x72, 0x61, 0x63, 0x6b,
0x65, 0x72, 0x20, 0x31,
]); ]);
const dataPacketBuffer = new Uint8Array([ const dataPacketBuffer = new Uint8Array([
0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x67, 0x28, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x01,
0x00, 0x00, 0x00, 0x02, 0x03, 0x01, 0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x01, 0x01, 0x00, 0x14, 0x80, 0x01, 0x00, 0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
0x10, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
0x3f, 0x00, 0x00, 0x80, 0x3f,
]); ]);
decoder.decode(infoPacketBuffer); decoder.decode(infoPacketBuffer);
+4 -4
View File
@@ -16,11 +16,11 @@ const dataPackets = encoder.getDataPackets(timestamp, trackers);
const infoPackets = encoder.getInfoPackets(timestamp, trackers); const infoPackets = encoder.getInfoPackets(timestamp, trackers);
dataPackets.forEach((dataPacket) => { dataPackets.forEach((dataPacket) => {
console.log('send packet somehow'); console.log('send packet somehow');
console.log(dataPacket); console.log(dataPacket);
}); });
infoPackets.forEach((infoPacket) => { infoPackets.forEach((infoPacket) => {
console.log('send packet somehow'); console.log('send packet somehow');
console.log(infoPacket); console.log(infoPacket);
}); });
+35 -45
View File
@@ -1,66 +1,56 @@
// recreation of psn_client.cpp example from https://github.com/vyv/psn-cpp // recreation of psn_client.cpp example from https://github.com/vyv/psn-cpp
const dgram = require('node:dgram'); const dgram = require('dgram');
const { Decoder } = require('@jwetzell/posistagenet'); const { Decoder } = require('../dist/cjs');
const client = dgram.createSocket('udp4'); const client = dgram.createSocket('udp4');
const decoder = new Decoder(); const decoder = new Decoder();
client.on('listening', () => { client.on('listening', () => {
client.addMembership('236.10.10.10'); client.addMembership('236.10.10.10');
}); });
client.on('message', (buffer) => { client.on('message', (buffer) => {
decoder.decode(buffer); decoder.decode(buffer);
}); });
client.bind(56565, '0.0.0.0'); client.bind(56565, '0.0.0.0');
setInterval(() => { setInterval(() => {
if (decoder.system_name) { if (decoder.system_name) {
console.log(`System Name: ${decoder.system_name}`); console.log(`System Name: ${decoder.system_name}`);
} }
if (Object.keys(decoder.trackers).length > 0) { if (Object.keys(decoder.trackers).length > 0) {
console.log(`Tracker Count: ${Object.keys(decoder.trackers).length}`); console.log(`Tracker Count: ${Object.keys(decoder.trackers).length}`);
} }
Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => { Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => {
const trackerName = decoder.trackers[trackerId]?.name; const trackerName = decoder.trackers[trackerId]?.name;
console.log(`Tracker - id: ${trackerId} | name: ${trackerName || ''}`); console.log(`Tracker - id: ${trackerId} | name: ${trackerName || ''}`);
if (tracker.pos) { if (tracker.pos) {
console.log( console.log(`\tpos: ${tracker.pos.x}, ${tracker.pos.x}, ${tracker.pos.x}`);
`\tpos: ${tracker.pos.x}, ${tracker.pos.x}, ${tracker.pos.x}` }
);
}
if (tracker.speed) { if (tracker.speed) {
console.log( console.log(`\tspeed: ${tracker.speed.x}, ${tracker.speed.y}, ${tracker.speed.z}`);
`\tspeed: ${tracker.speed.x}, ${tracker.speed.y}, ${tracker.speed.z}` }
);
}
if (tracker.ori) { if (tracker.ori) {
console.log( console.log(`\tori: ${tracker.ori.x}, ${tracker.ori.y}, ${tracker.ori.z}`);
`\tori: ${tracker.ori.x}, ${tracker.ori.y}, ${tracker.ori.z}` }
);
}
if (tracker.status) { if (tracker.status) {
console.log(`\tstatus: ${tracker.status.validity}`); console.log(`\tstatus: ${tracker.status.validity}`);
} }
if (tracker.accel) { if (tracker.accel) {
console.log( console.log(`\taccel: ${tracker.accel.x}, ${tracker.accel.y}, ${tracker.accel.z}`);
`\taccel: ${tracker.accel.x}, ${tracker.accel.y}, ${tracker.accel.z}` }
);
}
if (tracker.trgtpos) { if (tracker.trgtpos) {
console.log( console.log(`\ttrgtpos: ${tracker.trgtpos.x}, ${tracker.trgtpos.y}, ${tracker.trgtpos.z}`);
`\ttrgtpos: ${tracker.trgtpos.x}, ${tracker.trgtpos.y}, ${tracker.trgtpos.z}` }
);
}
if (tracker.timestamp) { if (tracker.timestamp) {
console.log(`\ttimestamp: ${tracker.timestamp}`); console.log(`\ttimestamp: ${tracker.timestamp}`);
} }
}); });
}, 1000); }, 1000);
+28 -30
View File
@@ -1,6 +1,6 @@
// recreation of psn_server.cpp example from https://github.com/vyv/psn-cpp // recreation of psn_server.cpp example from https://github.com/vyv/psn-cpp
const dgram = require('node:dgram'); const dgram = require('dgram');
const { Encoder, Tracker } = require('@jwetzell/posistagenet'); const { Encoder, Tracker } = require('../dist/cjs');
const client = dgram.createSocket('udp4'); const client = dgram.createSocket('udp4');
const encoder = new Encoder('Test PSN Server', 2, 0); const encoder = new Encoder('Test PSN Server', 2, 0);
@@ -19,40 +19,38 @@ trackers.push(new Tracker(8, 'Neptune'));
trackers.push(new Tracker(9, 'Pluto')); trackers.push(new Tracker(9, 'Pluto'));
const orbits = [1.0, 88.0, 224.7, 365.2, 687, 4332, 10760, 30700, 60200, 90600]; const orbits = [1.0, 88.0, 224.7, 365.2, 687, 4332, 10760, 30700, 60200, 90600];
const distFromSun = [ const distFromSun = [0, 0.58, 1.08, 1.5, 2.28, 7.78, 14.29, 28.71, 45.04, 59.13];
0, 0.58, 1.08, 1.5, 2.28, 7.78, 14.29, 28.71, 45.04, 59.13,
];
let timestamp = 0; let timestamp = 0;
setInterval(() => { setInterval(() => {
orbits.forEach((_, index) => { orbits.forEach((orbit, index) => {
const a = 1.0 / orbits[index]; const a = 1.0 / orbits[index];
const b = distFromSun[index]; const b = distFromSun[index];
const x = timestamp; const x = timestamp;
const cb = Math.cos(a * x) * b; const cb = Math.cos(a * x) * b;
const sb = Math.sin(a * x) * b; const sb = Math.sin(a * x) * b;
trackers[index].setPos(sb, 0, cb); trackers[index].setPos(sb, 0, cb);
trackers[index].setSpeed(a * cb, 0, -a * sb); trackers[index].setSpeed(a * cb, 0, -a * sb);
trackers[index].setOri(0, x / 1000.0, 0); trackers[index].setOri(0, x / 1000.0, 0);
trackers[index].setAccel(-a * a * sb, 0, -a * a * cb); trackers[index].setAccel(-a * a * sb, 0, -a * a * cb);
trackers[index].setTrgtPos(3, 14, 16); trackers[index].setTrgtPos(3, 14, 16);
trackers[index].setStatus(index / 10.0); trackers[index].setStatus(index / 10.0);
trackers[index].setTimestamp(timestamp); trackers[index].setTimestamp(timestamp);
}); });
console.log(`Sending Data Packets`); console.log(`Sending Data Packets`);
const dataPackets = encoder.getDataPackets(timestamp, trackers); const dataPackets = encoder.getDataPackets(timestamp, trackers);
dataPackets.forEach((packet) => { dataPackets.forEach((packet) => {
client.send(packet, 56565, '236.10.10.10'); client.send(packet, 56565, '236.10.10.10');
}); });
timestamp += 1; timestamp += 1;
}, 5); }, 5);
setInterval(() => { setInterval(() => {
console.log(`Sending Info Packets`); console.log(`Sending Info Packets`);
const infoPackets = encoder.getInfoPackets(timestamp, trackers); const infoPackets = encoder.getInfoPackets(timestamp, trackers);
infoPackets.forEach((packet) => { infoPackets.forEach((packet) => {
client.send(packet, 56565, '236.10.10.10'); client.send(packet, 56565, '236.10.10.10');
}); });
}, 500); }, 500);
+4004 -1935
View File
File diff suppressed because it is too large Load Diff
+45 -45
View File
@@ -1,47 +1,47 @@
{ {
"name": "@jwetzell/posistagenet", "name": "@jwetzell/posistagenet",
"version": "2.1.2", "version": "2.0.0",
"description": "", "description": "",
"main": "./dist/index.cjs", "main": "./dist/cjs/index.js",
"module": "./dist/index.mjs", "module": "./dist/esm/index.js",
"types": "./dist/index.d.cts", "types": "./dist/types/index.d.ts",
"exports": { "exports": {
".": { ".": {
"import": "./dist/index.mjs", "import": "./dist/esm/index.js",
"require": "./dist/index.cjs" "require": "./dist/cjs/index.js",
}, "types": "./dist/types/index.d.ts"
"./package.json": "./package.json" }
}, },
"scripts": { "scripts": {
"prebuild": "rimraf dist", "prebuild": "rimraf dist",
"build": "tsdown", "build": "npm run build:cjs && npm run build:esm && npm run build:types",
"example:client": "node examples/psn_client.js", "build:cjs": "tsc -p tsconfig.cjs.json",
"example:server": "node examples/psn_server.js", "build:esm": "tsc -p tsconfig.esm.json",
"prepublishOnly": "npm run build", "build:types": "tsc -p tsconfig.types.json",
"lint:check": "biome lint", "example:client": "node examples/psn_client.js",
"lint:write": "biome lint --write", "example:server": "node examples/psn_server.js",
"format:check": "biome format", "prepublishOnly": "npm run build",
"format:write": "biome format --write", "lint:check": "eslint ./",
"pretest": "npm run build", "format:check": "prettier ./ --check",
"test": "node --test --experimental-test-coverage" "format:write": "prettier ./ --write"
}, },
"files": [ "files": [
"dist" "dist"
], ],
"author": { "author": {
"name": "Joel Wetzell", "name": "Joel Wetzell",
"email": "me@jwetzell.com", "email": "me@jwetzell.com",
"url": "https://jwetzell.com" "url": "https://jwetzell.com"
}, },
"repository": "https://github.com/jwetzell/psn-js", "repository": "https://github.com/jwetzell/psn-js",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.5.7", "@types/node": "22.10.2",
"@eslint/js": "10.0.1", "prettier": "3.4.2",
"@types/node": "24.7.2", "rimraf": "6.0.1",
"globals": "17.9.0", "typescript": "5.7.2",
"rimraf": "6.1.3", "eslint": "8.48.0",
"tsdown": "0.22.14", "eslint-config-airbnb": "19.0.4",
"typescript": "7.0.2" "eslint-config-prettier": "9.0.0"
} }
} }
+3 -3
View File
@@ -1,5 +1,5 @@
export class Constants { export class Constants {
static readonly PACKET_HEADER_SIZE = 16; static readonly PACKET_HEADER_SIZE = 16;
static readonly MAX_UDP_PACKET_SIZE = 1500; static readonly MAX_UDP_PACKET_SIZE = 1500;
static readonly CHUNK_HEADER_SIZE = 4; static readonly CHUNK_HEADER_SIZE = 4;
} }
+99 -118
View File
@@ -1,132 +1,113 @@
import { Decoders } from './index.js'; import { Decoders } from '.';
import { import { DataPacketChunk, InfoPacketChunk, Tracker, TrackerFromData, TrackerFromInfo } from './models';
type DataPacketChunk,
type InfoPacketChunk,
type Tracker,
TrackerFromData,
TrackerFromInfo,
} from './models/index.js';
export class Decoder { export class Decoder {
infoPacketFrames: { [key: number]: InfoPacketChunk[] } = {}; infoPacketFrames: { [key: number]: InfoPacketChunk[] } = {};
dataPacketFrames: { [key: number]: DataPacketChunk[] } = {}; dataPacketFrames: { [key: number]: DataPacketChunk[] } = {};
trackers: { [key: string]: Tracker } = {}; trackers: { [key: string]: Tracker } = {};
systemName: string = ''; systemName: string = '';
constructor() {}
updateInfo(framePackets: InfoPacketChunk[]) { updateInfo(framePackets: InfoPacketChunk[]) {
framePackets.forEach((packet) => { framePackets.forEach((packet) => {
if (packet.data.systemName?.data) { if (packet.data.systemName?.data) {
this.systemName = packet.data.systemName?.data.systemName; this.systemName = packet.data.systemName?.data.systemName;
} }
if (packet.data.trackerList?.data) { if (packet.data.trackerList?.data) {
packet.data.trackerList.data.trackers.forEach((infoTrackerChunk) => { packet.data.trackerList.data.trackers.forEach((infoTrackerChunk) => {
if (!this.trackers[infoTrackerChunk.chunk.header.id]) { if (!this.trackers[infoTrackerChunk.chunk.header.id]) {
const tracker = TrackerFromInfo(infoTrackerChunk); const tracker = TrackerFromInfo(infoTrackerChunk);
if (tracker) { if (tracker) {
this.trackers[infoTrackerChunk.chunk.header.id] = tracker; this.trackers[infoTrackerChunk.chunk.header.id] = tracker;
} }
} }
const tracker = this.trackers[infoTrackerChunk.chunk.header.id]; const tracker = this.trackers[infoTrackerChunk.chunk.header.id];
tracker.updateInfo(infoTrackerChunk); tracker.updateInfo(infoTrackerChunk);
}); });
} }
}); });
} }
updateData(framePackets: DataPacketChunk[]) { updateData(framePackets: DataPacketChunk[]) {
framePackets.forEach((packet) => { framePackets.forEach((packet) => {
if (packet.data.trackerList) { if (packet.data.trackerList) {
packet.data.trackerList?.data.trackers.forEach((dataTrackerChunk) => { packet.data.trackerList?.data.trackers.forEach((dataTrackerChunk) => {
if (!this.trackers[dataTrackerChunk.chunk.header.id]) { if (!this.trackers[dataTrackerChunk.chunk.header.id]) {
const tracker = TrackerFromData(dataTrackerChunk); const tracker = TrackerFromData(dataTrackerChunk);
if (tracker) { if (tracker) {
this.trackers[dataTrackerChunk.chunk.header.id] = tracker; this.trackers[dataTrackerChunk.chunk.header.id] = tracker;
} }
} }
const tracker = this.trackers[dataTrackerChunk.chunk.header.id]; const tracker = this.trackers[dataTrackerChunk.chunk.header.id];
tracker.updateData(dataTrackerChunk); tracker.updateData(dataTrackerChunk);
}); });
} }
}); });
} }
// TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete // TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete
decode(packetBuf: Uint8Array) { decode(packetBuf: Uint8Array) {
const packet = Decoders.Chunk(packetBuf); const packet = Decoders.Chunk(packetBuf);
if (packet === undefined) { if (packet === undefined) {
return packet; return packet;
} }
if (packet.header.id === 0x6756) { if (packet.header.id === 0x6756) {
const infoPacket = Decoders.InfoPacketChunk(packetBuf); const infoPacket = Decoders.InfoPacketChunk(packetBuf);
if (infoPacket?.chunk.header.hasSubchunks) { if (infoPacket && infoPacket.chunk.header.hasSubchunks) {
const currentInfoPacketHeader = infoPacket.data.packetHeader; const currentInfoPacketHeader = infoPacket.data.packetHeader;
if (!currentInfoPacketHeader) { if (!currentInfoPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid? // NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet'); throw new Error('malformed packet');
} }
const systemSubChunk = infoPacket.data.systemName; const systemSubChunk = infoPacket.data.systemName;
if (!systemSubChunk) { if (!systemSubChunk) {
// NOTE(jwetzell): not sure that info packets without a system subchunk are valid? // NOTE(jwetzell): not sure that info packets without a system subchunk are valid?
throw new Error('malformed packet'); throw new Error('malformed packet');
} }
if (currentInfoPacketHeader.data.frameId) { if (currentInfoPacketHeader.data.frameId) {
if ( if (this.infoPacketFrames[currentInfoPacketHeader.data.frameId] === undefined) {
this.infoPacketFrames[currentInfoPacketHeader.data.frameId] === this.infoPacketFrames[currentInfoPacketHeader.data.frameId] = [];
undefined }
) { this.infoPacketFrames[currentInfoPacketHeader.data.frameId].push(infoPacket);
this.infoPacketFrames[currentInfoPacketHeader.data.frameId] = [];
}
this.infoPacketFrames[currentInfoPacketHeader.data.frameId].push(
infoPacket
);
if ( if (
this.infoPacketFrames[currentInfoPacketHeader.data.frameId] this.infoPacketFrames[currentInfoPacketHeader.data.frameId].length ===
.length === currentInfoPacketHeader.data.framePacketCount currentInfoPacketHeader.data.framePacketCount
) { ) {
this.updateInfo( this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.data.frameId]);
this.infoPacketFrames[currentInfoPacketHeader.data.frameId] delete this.infoPacketFrames[currentInfoPacketHeader.data.frameId];
); }
delete this.infoPacketFrames[currentInfoPacketHeader.data.frameId]; }
} }
} } else if (packet.header.id === 0x6755) {
} const dataPacket = Decoders.DataPacketChunk(packetBuf);
} else if (packet.header.id === 0x6755) { if (dataPacket.chunk.header.hasSubchunks) {
const dataPacket = Decoders.DataPacketChunk(packetBuf); const currentDataPacketHeader = dataPacket.data.packetHeader;
if (dataPacket.chunk.header.hasSubchunks) { if (!currentDataPacketHeader) {
const currentDataPacketHeader = dataPacket.data.packetHeader; // NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
if (!currentDataPacketHeader) { throw new Error('malformed packet');
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid? }
throw new Error('malformed packet');
}
if (currentDataPacketHeader.data.frameId) { if (currentDataPacketHeader.data.frameId) {
if ( if (this.dataPacketFrames[currentDataPacketHeader.data.frameId] === undefined) {
this.dataPacketFrames[currentDataPacketHeader.data.frameId] === this.dataPacketFrames[currentDataPacketHeader.data.frameId] = [];
undefined }
) { this.dataPacketFrames[currentDataPacketHeader.data.frameId].push(dataPacket);
this.dataPacketFrames[currentDataPacketHeader.data.frameId] = []; if (
} this.dataPacketFrames[currentDataPacketHeader.data.frameId].length ===
this.dataPacketFrames[currentDataPacketHeader.data.frameId].push( currentDataPacketHeader.data.framePacketCount
dataPacket ) {
); this.updateData(this.dataPacketFrames[currentDataPacketHeader.data.frameId]);
if ( delete this.dataPacketFrames[currentDataPacketHeader.data.frameId];
this.dataPacketFrames[currentDataPacketHeader.data.frameId] }
.length === currentDataPacketHeader.data.framePacketCount }
) { }
this.updateData( }
this.dataPacketFrames[currentDataPacketHeader.data.frameId] }
);
delete this.dataPacketFrames[currentDataPacketHeader.data.frameId];
}
}
}
}
}
} }
+21 -23
View File
@@ -1,31 +1,29 @@
import type { Chunk } from '../models/chunk.js'; import { Chunk } from '../models/chunk';
export default (buffer: Uint8Array): Chunk => { export default (buffer: Uint8Array): Chunk => {
if (buffer.length < 4) { let offset = 0;
throw new Error('Chunk buffer must be at least 4 bytes'); const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
} const id = view.getUint16(offset, true);
offset += 2;
const id = (buffer[1] << 8) + buffer[0]; // NOTE(jwetzell): this data is split up as 1 bit for has_subchunks and 15 bits for the data_len
const combinedLengthAndFlag = view.getUint16(offset, true);
const hasSubchunks = combinedLengthAndFlag > 32768;
const dataLen = hasSubchunks ? combinedLengthAndFlag - 32768 : combinedLengthAndFlag;
offset += 2;
// NOTE(jwetzell): this data is split up as 1 bit for hasSubchunks and 15 bits for the dataLen const header = {
const combinedLengthAndFlag = (buffer[3] << 8) + buffer[2]; id,
const hasSubchunks = combinedLengthAndFlag > 32768; dataLen,
const dataLen = hasSubchunks hasSubchunks,
? combinedLengthAndFlag - 32768 };
: combinedLengthAndFlag;
const header = { const chunkData = buffer.subarray(offset, offset + header.dataLen);
id,
dataLen,
hasSubchunks,
};
const chunkData = buffer.subarray(4, 4 + header.dataLen); const chunk = {
chunkData,
header,
};
const chunk = { return chunk;
chunkData,
header,
};
return chunk;
}; };
+34 -42
View File
@@ -1,48 +1,40 @@
import { Constants } from '../../constants.js'; import { Decoders } from '..';
import type { import { Constants } from '../../constants';
DataPacketChunk, import { DataPacketChunk, DataPacketChunkData } from '../../models/data/data-packet-chunk';
DataPacketChunkData,
} from '../../models/data/data-packet-chunk.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): DataPacketChunk => { export default (buffer: Uint8Array): DataPacketChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const data: DataPacketChunkData = {}; const data: DataPacketChunkData = {};
if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) { if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) {
let offset = 0; let offset = 0;
while (offset < chunk.header.dataLen) { while (offset < chunk.header.dataLen) {
const chunkId = const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
(chunk.chunkData.subarray(offset)[1] << 8) + const chunkId = view.getUint16(offset, true);
chunk.chunkData.subarray(offset)[0]; switch (chunkId) {
switch (chunkId) { case 0x0000:
case 0x0000: data.packetHeader = Decoders.PacketHeaderChunk(chunk.chunkData.subarray(offset));
data.packetHeader = Decoders.PacketHeaderChunk( offset += Constants.CHUNK_HEADER_SIZE;
chunk.chunkData.subarray(offset) if (data.packetHeader.chunk.header.dataLen) {
); offset += data.packetHeader.chunk.header.dataLen;
offset += Constants.CHUNK_HEADER_SIZE; }
if (data.packetHeader.chunk.header.dataLen) { break;
offset += data.packetHeader.chunk.header.dataLen; case 0x0001:
} data.trackerList = Decoders.DataTrackerListChunk(chunk.chunkData.subarray(offset));
break; offset += Constants.CHUNK_HEADER_SIZE;
case 0x0001: if (data.trackerList.chunk.header.dataLen) {
data.trackerList = Decoders.DataTrackerListChunk( offset += data.trackerList.chunk.header.dataLen;
chunk.chunkData.subarray(offset) }
); break;
offset += Constants.CHUNK_HEADER_SIZE; default:
if (data.trackerList.chunk.header.dataLen) { break;
offset += data.trackerList.chunk.header.dataLen; }
} }
break; }
default:
break;
}
}
}
return { return {
chunk, chunk,
data, data,
}; };
}; };
+42 -61
View File
@@ -1,65 +1,46 @@
import { Constants } from '../../constants.js'; import { Decoders } from '..';
import type { import { Constants } from '../../constants';
DataTrackerChunk, import { DataTrackerChunk, DataTrackerChunkData } from '../../models/data/data-tracker-chunk';
DataTrackerChunkData,
} from '../../models/data/data-tracker-chunk.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): DataTrackerChunk => { export default (buffer: Uint8Array): DataTrackerChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const data: DataTrackerChunkData = {}; const data: DataTrackerChunkData = {};
if (chunk.chunkData && chunk.header.dataLen) { if (chunk.chunkData && chunk.header.dataLen) {
let offset = 0; let offset = 0;
while (offset < chunk.header.dataLen) { while (offset < chunk.header.dataLen) {
const trackerFieldChunk = Decoders.Chunk( const trackerFieldChunk = Decoders.Chunk(chunk.chunkData.subarray(offset));
chunk.chunkData.subarray(offset) switch (trackerFieldChunk.header.id) {
); case 0x0000:
switch (trackerFieldChunk.header.id) { data.pos = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
case 0x0000: break;
data.pos = Decoders.DataTrackerXYZChunk( case 0x0001:
chunk.chunkData.subarray(offset) data.speed = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
); break;
break; case 0x0002:
case 0x0001: data.ori = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
data.speed = Decoders.DataTrackerXYZChunk( break;
chunk.chunkData.subarray(offset) case 0x0003:
); data.status = Decoders.DataTrackerStatusChunk(chunk.chunkData.subarray(offset));
break; break;
case 0x0002: case 0x0004:
data.ori = Decoders.DataTrackerXYZChunk( data.accel = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
chunk.chunkData.subarray(offset) break;
); case 0x0005:
break; data.trgtpos = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset));
case 0x0003: break;
data.status = Decoders.DataTrackerStatusChunk( case 0x0006:
chunk.chunkData.subarray(offset) data.timestamp = Decoders.DataTrackerTimestampChunk(chunk.chunkData.subarray(offset));
); break;
break; default:
case 0x0004: break;
data.accel = Decoders.DataTrackerXYZChunk( }
chunk.chunkData.subarray(offset) offset += Constants.CHUNK_HEADER_SIZE;
); offset += trackerFieldChunk.header.dataLen;
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;
}
}
return { return {
chunk, chunk,
data, data,
}; };
}; };
+27 -32
View File
@@ -1,38 +1,33 @@
import { Constants } from '../../constants.js'; import { Decoders } from '..';
import type { import { Constants } from '../../constants';
DataTrackerListChunk, import { DataTrackerChunk } from '../../models';
DataTrackerListChunkData, import { DataTrackerListChunk, DataTrackerListChunkData } from '../../models/data/data-tracker-list-chunk';
} from '../../models/data/data-tracker-list-chunk.js';
import type { DataTrackerChunk } from '../../models/index.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): DataTrackerListChunk => { export default (buffer: Uint8Array): DataTrackerListChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const trackers: DataTrackerChunk[] = []; const trackers: DataTrackerChunk[] = [];
// TODO(jwetzell): add error handling // TODO(jwetzell): add error handling
if (chunk.chunkData) { if (chunk.chunkData) {
let offset = 0; let offset = 0;
while (offset < chunk.chunkData.length) { while (offset < chunk.chunkData.length) {
const trackerChunk = Decoders.DataTrackerChunk( const trackerChunk = Decoders.DataTrackerChunk(chunk.chunkData.subarray(offset));
chunk.chunkData.subarray(offset) offset += Constants.CHUNK_HEADER_SIZE;
); if (trackerChunk.chunk.header.dataLen) {
offset += Constants.CHUNK_HEADER_SIZE; offset += trackerChunk.chunk.header.dataLen;
if (trackerChunk.chunk.header.dataLen) { }
offset += trackerChunk.chunk.header.dataLen; if (trackerChunk.chunk.header.id !== undefined) {
} trackers.push(trackerChunk);
if (trackerChunk.chunk.header.id !== undefined) { }
trackers.push(trackerChunk); }
} }
}
}
const data: DataTrackerListChunkData = { const data: DataTrackerListChunkData = {
trackers, trackers,
}; };
return { return {
chunk, chunk,
data, data,
}; };
}; };
+14 -19
View File
@@ -1,25 +1,20 @@
import type { /* eslint-disable no-case-declarations */
DataTrackerStatusChunk,
DataTrackerStatusChunkData, import { Decoders } from '..';
} from '../../models/data/data-tracker-status-chunk.js'; import { DataTrackerStatusChunk, DataTrackerStatusChunkData } from '../../models/data/data-tracker-status-chunk';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): DataTrackerStatusChunk => { export default (buffer: Uint8Array): DataTrackerStatusChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const view = new DataView( const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
chunk.chunkData.buffer, const validity = view.getFloat32(0, true);
chunk.chunkData.byteOffset,
chunk.chunkData.byteLength
);
const validity = view.getFloat32(0, true);
const data: DataTrackerStatusChunkData = { const data: DataTrackerStatusChunkData = {
validity, validity,
}; };
return { return {
chunk, chunk,
data, data,
}; };
}; };
@@ -1,25 +1,23 @@
import type { /* eslint-disable no-case-declarations */
DataTrackerTimestampChunk,
DataTrackerTimestampChunkData, import { Decoders } from '..';
} from '../../models/data/data-tracker-timestamp-chunk.js'; import {
import { Decoders } from '../index.js'; DataTrackerTimestampChunk,
DataTrackerTimestampChunkData,
} from '../../models/data/data-tracker-timestamp-chunk';
export default (buffer: Uint8Array): DataTrackerTimestampChunk => { export default (buffer: Uint8Array): DataTrackerTimestampChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const view = new DataView( const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
chunk.chunkData.buffer, const timestamp = view.getBigUint64(0, true);
chunk.chunkData.byteOffset,
chunk.chunkData.byteLength
);
const timestamp = view.getBigUint64(0, true);
const data: DataTrackerTimestampChunkData = { const data: DataTrackerTimestampChunkData = {
timestamp, timestamp,
}; };
return { return {
chunk, chunk,
data, data,
}; };
}; };
+14 -21
View File
@@ -1,27 +1,20 @@
import type { import { Decoders } from '..';
DataTrackerXYZChunk, import { DataTrackerXYZChunk, DataTrackerXYZChunkData } from '../../models/data/data-tracker-xyz-chunk';
DataTrackerXYZChunkData,
} from '../../models/data/data-tracker-xyz-chunk.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): DataTrackerXYZChunk => { export default (buffer: Uint8Array): DataTrackerXYZChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
// TODO(jwetzell): add error handling // TODO(jwetzell): add error handling
const view = new DataView( const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
chunk.chunkData.buffer,
chunk.chunkData.byteOffset,
chunk.chunkData.byteLength
);
const data: DataTrackerXYZChunkData = { const data: DataTrackerXYZChunkData = {
x: view.getFloat32(0, true), x: view.getFloat32(0, true),
y: view.getFloat32(4, true), y: view.getFloat32(4, true),
z: view.getFloat32(8, true), z: view.getFloat32(8, true),
}; };
return { return {
chunk, chunk,
data, data,
}; };
}; };
+28 -26
View File
@@ -1,31 +1,33 @@
import Chunk from './chunk.js'; import Chunk from './chunk';
import PacketHeaderChunk from './packet-header-chunk.js'; import Packet from './packet';
import PacketHeaderChunk from './packet-header-chunk';
import DataPacketChunk from './data/data-packet-chunk.js'; import DataPacketChunk from './data/data-packet-chunk';
import DataTrackerChunk from './data/data-tracker-chunk.js'; import DataTrackerChunk from './data/data-tracker-chunk';
import DataTrackerListChunk from './data/data-tracker-list-chunk.js'; import DataTrackerListChunk from './data/data-tracker-list-chunk';
import DataTrackerStatusChunk from './data/data-tracker-status-chunk.js'; import DataTrackerStatusChunk from './data/data-tracker-status-chunk';
import DataTrackerTimestampChunk from './data/data-tracker-timestamp-chunk.js'; import DataTrackerTimestampChunk from './data/data-tracker-timestamp-chunk';
import DataTrackerXYZChunk from './data/data-tracker-xyz-chunk.js'; import DataTrackerXYZChunk from './data/data-tracker-xyz-chunk';
import InfoPacketChunk from './info/info-packet-chunk.js'; import InfoPacketChunk from './info/info-packet-chunk';
import InfoSystemNameChunk from './info/info-system-name-chunk.js'; import InfoSystemNameChunk from './info/info-system-name-chunk';
import InfoTrackerChunk from './info/info-tracker-chunk.js'; import InfoTrackerChunk from './info/info-tracker-chunk';
import InfoTrackerListChunk from './info/info-tracker-list-chunk.js'; import InfoTrackerListChunk from './info/info-tracker-list-chunk';
import InfoTrackerNameChunk from './info/info-tracker-name-chunk.js'; import InfoTrackerNameChunk from './info/info-tracker-name-chunk';
export const Decoders = { export const Decoders = {
Chunk, Chunk,
PacketHeaderChunk, PacketHeaderChunk,
DataPacketChunk, Packet,
DataTrackerChunk, DataPacketChunk,
DataTrackerXYZChunk, DataTrackerChunk,
DataTrackerStatusChunk, DataTrackerXYZChunk,
DataTrackerTimestampChunk, DataTrackerStatusChunk,
DataTrackerListChunk, DataTrackerTimestampChunk,
InfoPacketChunk, DataTrackerListChunk,
InfoSystemNameChunk, InfoPacketChunk,
InfoTrackerChunk, InfoSystemNameChunk,
InfoTrackerListChunk, InfoTrackerChunk,
InfoTrackerNameChunk, InfoTrackerListChunk,
InfoTrackerNameChunk,
}; };
+41 -51
View File
@@ -1,57 +1,47 @@
import { Constants } from '../../constants.js'; import { Decoders } from '..';
import type { import { Constants } from '../../constants';
InfoPacketChunk, import { InfoPacketChunk, InfoPacketChunkData } from '../../models/info/info-packet-chunk';
InfoPacketChunkData,
} from '../../models/info/info-packet-chunk.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): InfoPacketChunk => { export default (buffer: Uint8Array): InfoPacketChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const data: InfoPacketChunkData = {}; const data: InfoPacketChunkData = {};
if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) { if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) {
let offset = 0; let offset = 0;
while (offset < chunk.header.dataLen) { while (offset < chunk.header.dataLen) {
const chunkId = const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
(chunk.chunkData.subarray(offset)[1] << 8) + const chunkId = view.getUint16(offset, true);
chunk.chunkData.subarray(offset)[0]; switch (chunkId) {
switch (chunkId) { case 0x0000:
case 0x0000: data.packetHeader = Decoders.PacketHeaderChunk(chunk.chunkData.subarray(offset));
data.packetHeader = Decoders.PacketHeaderChunk( offset += Constants.CHUNK_HEADER_SIZE;
chunk.chunkData.subarray(offset) if (data.packetHeader?.chunk.header.dataLen) {
); offset += data.packetHeader.chunk.header.dataLen;
offset += Constants.CHUNK_HEADER_SIZE; }
if (data.packetHeader?.chunk.header.dataLen) { break;
offset += data.packetHeader.chunk.header.dataLen; case 0x0001:
} data.systemName = Decoders.InfoSystemNameChunk(chunk.chunkData.subarray(offset));
break; offset += Constants.CHUNK_HEADER_SIZE;
case 0x0001: if (data.systemName?.chunk.header.dataLen) {
data.systemName = Decoders.InfoSystemNameChunk( offset += data.systemName?.chunk.header.dataLen;
chunk.chunkData.subarray(offset) }
); break;
offset += Constants.CHUNK_HEADER_SIZE; case 0x0002:
if (data.systemName?.chunk.header.dataLen) { data.trackerList = Decoders.InfoTrackerListChunk(chunk.chunkData.subarray(offset));
offset += data.systemName?.chunk.header.dataLen; offset += Constants.CHUNK_HEADER_SIZE;
} if (data.trackerList?.chunk.header.dataLen) {
break; offset += data.trackerList.chunk.header.dataLen;
case 0x0002: }
data.trackerList = Decoders.InfoTrackerListChunk( break;
chunk.chunkData.subarray(offset) default:
); break;
offset += Constants.CHUNK_HEADER_SIZE; }
if (data.trackerList?.chunk.header.dataLen) { }
offset += data.trackerList.chunk.header.dataLen; }
}
break;
default:
break;
}
}
}
return { return {
chunk, chunk,
data, data,
}; };
}; };
+10 -16
View File
@@ -1,21 +1,15 @@
import type { import { Decoders } from '..';
InfoSystemNameChunk, import { InfoSystemNameChunk, InfoSystemNameChunkData } from '../../models/info/info-system-name-chunk';
InfoSystemNameChunkData,
} from '../../models/info/info-system-name-chunk.js';
import { Decoders } from '../index.js';
const nameDecoder = new TextDecoder();
export default (buffer: Uint8Array): InfoSystemNameChunk => { export default (buffer: Uint8Array): InfoSystemNameChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const data: InfoSystemNameChunkData = { const data: InfoSystemNameChunkData = {
systemName: nameDecoder.decode( systemName: new TextDecoder().decode(chunk.chunkData.subarray(0, chunk.header.dataLen)),
chunk.chunkData.subarray(0, chunk.header.dataLen) };
),
};
return { return {
chunk, chunk,
data, data,
}; };
}; };
+31 -37
View File
@@ -1,42 +1,36 @@
import { Constants } from '../../constants.js'; import { Decoders } from '..';
import type { import { Constants } from '../../constants';
InfoTrackerChunk, import { InfoTrackerChunk, InfoTrackerChunkData } from '../../models/info/info-tracker-chunk';
InfoTrackerChunkData,
} from '../../models/info/info-tracker-chunk.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): InfoTrackerChunk => { export default (buffer: Uint8Array): InfoTrackerChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) { if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) {
let offset = 0; let offset = 0;
while (offset < chunk.header.dataLen) { while (offset < chunk.header.dataLen) {
const chunkId = const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
(chunk.chunkData.subarray(offset)[1] << 8) + const chunkId = view.getUint16(offset, true);
chunk.chunkData.subarray(offset)[0]; switch (chunkId) {
switch (chunkId) { case 0x0000:
case 0x0000: { const data: InfoTrackerChunkData = {
const data: InfoTrackerChunkData = { trackerName: Decoders.InfoTrackerNameChunk(chunk.chunkData.subarray(offset)),
trackerName: Decoders.InfoTrackerNameChunk( };
chunk.chunkData.subarray(offset) offset += Constants.CHUNK_HEADER_SIZE;
), if (data.trackerName.chunk.header.dataLen) {
}; offset += data.trackerName.chunk.header.dataLen;
offset += Constants.CHUNK_HEADER_SIZE; }
if (data.trackerName.chunk.header.dataLen) { return {
offset += data.trackerName.chunk.header.dataLen; chunk,
} data,
return { };
chunk,
data,
};
}
default:
break;
}
}
}
return { default:
chunk, break;
}; }
}
}
return {
chunk,
};
}; };
+28 -33
View File
@@ -1,38 +1,33 @@
import { Constants } from '../../constants.js'; import { Decoders } from '..';
import type { InfoTrackerChunk } from '../../models/info/info-tracker-chunk.js'; import { Constants } from '../../constants';
import type { import { InfoTrackerChunk } from '../../models/info/info-tracker-chunk';
InfoTrackerListChunk, import { InfoTrackerListChunk, InfoTrackerListChunkData } from '../../models/info/info-tracker-list-chunk';
InfoTrackerListChunkData,
} from '../../models/info/info-tracker-list-chunk.js';
import { Decoders } from '../index.js';
export default (buffer: Uint8Array): InfoTrackerListChunk => { export default (buffer: Uint8Array): InfoTrackerListChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const trackers: InfoTrackerChunk[] = []; const trackers: InfoTrackerChunk[] = [];
if (chunk.header.hasSubchunks && chunk.chunkData) { if (chunk.header.hasSubchunks && chunk.chunkData) {
let offset = 0; let offset = 0;
if (chunk.header.dataLen) { if (chunk.header.dataLen) {
while (offset < chunk.header.dataLen) { while (offset < chunk.header.dataLen) {
const trackerChunk = Decoders.InfoTrackerChunk( const trackerChunk = Decoders.InfoTrackerChunk(chunk.chunkData.subarray(offset));
chunk.chunkData.subarray(offset) offset += Constants.CHUNK_HEADER_SIZE;
); if (trackerChunk.chunk.header.dataLen) {
offset += Constants.CHUNK_HEADER_SIZE; offset += trackerChunk.chunk.header.dataLen;
if (trackerChunk.chunk.header.dataLen) { }
offset += trackerChunk.chunk.header.dataLen; if (trackerChunk.chunk.header.id !== undefined) {
} trackers.push(trackerChunk);
if (trackerChunk.chunk.header.id !== undefined) { }
trackers.push(trackerChunk); }
} }
} }
} const data: InfoTrackerListChunkData = {
} trackers,
const data: InfoTrackerListChunkData = { };
trackers, return {
}; chunk,
return { data,
chunk, };
data,
};
}; };
+10 -16
View File
@@ -1,21 +1,15 @@
import type { import { Decoders } from '..';
InfoTrackerNameChunk, import { InfoTrackerNameChunk, InfoTrackerNameChunkData } from '../../models/info/info-tracker-name-chunk';
InfoTrackerNameChunkData,
} from '../../models/info/info-tracker-name-chunk.js';
import { Decoders } from '../index.js';
const nameDecoder = new TextDecoder();
export default (buffer: Uint8Array): InfoTrackerNameChunk => { export default (buffer: Uint8Array): InfoTrackerNameChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
const data: InfoTrackerNameChunkData = { const data: InfoTrackerNameChunkData = {
trackerName: nameDecoder.decode( trackerName: new TextDecoder().decode(chunk.chunkData.subarray(0, chunk.header.dataLen)),
chunk.chunkData.subarray(0, chunk.header.dataLen) };
),
};
return { return {
chunk, chunk,
data, data,
}; };
}; };
+15 -25
View File
@@ -1,30 +1,20 @@
import type { import { Decoders } from '.';
PacketHeaderChunk, import { PacketHeaderChunk, PacketHeaderChunkData } from '../models/packet-header-chunk';
PacketHeaderChunkData,
} from '../models/packet-header-chunk.js';
import { Decoders } from './index.js';
export default (buffer: Uint8Array): PacketHeaderChunk => { export default (buffer: Uint8Array): PacketHeaderChunk => {
const chunk = Decoders.Chunk(buffer); const chunk = Decoders.Chunk(buffer);
let packetTimestamp = BigInt(chunk.chunkData[7]) << BigInt(56); const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength);
packetTimestamp += BigInt(chunk.chunkData[6]) << BigInt(48); const data: PacketHeaderChunkData = {
packetTimestamp += BigInt(chunk.chunkData[5]) << BigInt(40); packetTimestamp: view.getBigUint64(0, true),
packetTimestamp += BigInt(chunk.chunkData[4]) << BigInt(32); versionHigh: chunk.chunkData[8],
packetTimestamp += BigInt(chunk.chunkData[3]) << BigInt(24); versionLow: chunk.chunkData[9],
packetTimestamp += BigInt(chunk.chunkData[2]) << BigInt(16); frameId: chunk.chunkData[10],
packetTimestamp += BigInt(chunk.chunkData[1]) << BigInt(8); framePacketCount: chunk.chunkData[11],
packetTimestamp += BigInt(chunk.chunkData[0]); };
const data: PacketHeaderChunkData = {
packetTimestamp,
versionHigh: chunk.chunkData[8],
versionLow: chunk.chunkData[9],
frameId: chunk.chunkData[10],
framePacketCount: chunk.chunkData[11],
};
return { return {
chunk, chunk,
data, data,
}; };
}; };
+17
View File
@@ -0,0 +1,17 @@
import { Decoders } from '.';
import { DataPacketChunk } from '../models/data/data-packet-chunk';
import { InfoPacketChunk } from '../models/info/info-packet-chunk';
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);
case 0x6755:
return Decoders.DataPacketChunk(buffer);
default:
return undefined;
}
};
+110 -135
View File
@@ -1,157 +1,132 @@
import { Constants } from './constants.js'; import { Encoders, Tracker } from '.';
import { Encoders, type Tracker } from './index.js'; import { Constants } from './constants';
export class Encoder { export class Encoder {
private systemName: string; private systemName: string;
private versionHigh: number; private versionHigh: number;
private versionLow: number; private versionLow: number;
dataFrameId: number = 1; dataFrameId: number = 1;
infoFrameId: number = 1; infoFrameId: number = 1;
constructor( constructor(systemName: string, versionHigh: number = 2, versionLow: number = 3) {
systemName: string, this.systemName = systemName;
versionHigh: number = 2, this.versionHigh = versionHigh;
versionLow: number = 3 this.versionLow = versionLow;
) { }
this.systemName = systemName;
this.versionHigh = versionHigh;
this.versionLow = versionLow;
}
setSystemName(systemName: string) { setSystemName(systemName: string) {
this.systemName = systemName; this.systemName = systemName;
} }
setVersionHigh(versionHigh: number) { setVersionHigh(versionHigh: number) {
this.versionHigh = versionHigh; this.versionHigh = versionHigh;
} }
setVersionLow(versionLow: number) { setVersionLow(versionLow: number) {
this.versionLow = versionLow; this.versionLow = versionLow;
} }
resetDataFrameId() { resetDataFrameId() {
this.dataFrameId = 1; this.dataFrameId = 1;
} }
resetInfoFrameId() { resetInfoFrameId() {
this.infoFrameId = 1; this.infoFrameId = 1;
} }
getInfoPackets(timestamp: bigint, trackers: Tracker[], frameId?: number) { getInfoPackets(timestamp: bigint, trackers: Tracker[], frameId?: number) {
if (frameId !== undefined) { if (frameId !== undefined) {
if (!Number.isInteger(frameId)) { if (!Number.isInteger(frameId)) {
throw new Error('frame id must be an integer'); throw new Error('frame id must be an integer');
} }
if (frameId > 255 || frameId < 0) { if (frameId > 255 || frameId < 0) {
throw new Error('frame id must be >= 0 and <= 255'); throw new Error('frame id must be >= 0 and <= 255');
} }
} }
const systemNameChunk = Encoders.InfoSystemNameChunk(this.systemName); const systemNameChunk = Encoders.InfoSystemNameChunk(this.systemName);
const trackerChunks = trackers.map((tracker: Tracker) => const trackerChunks = trackers.map((tracker: Tracker) => tracker.getInfoChunk());
tracker.getInfoChunk()
);
const infoPackets: Uint8Array[] = []; const infoPackets: Uint8Array[] = [];
const trackerChunksLists: Uint8Array[][] = []; const trackerChunksLists: Uint8Array[][] = [];
let currentTrackerList: Uint8Array[] = []; let currentTrackerList: Uint8Array[] = [];
let currentInfoPacketSize = let currentInfoPacketSize = Constants.PACKET_HEADER_SIZE + systemNameChunk.length + Constants.CHUNK_HEADER_SIZE;
Constants.PACKET_HEADER_SIZE +
systemNameChunk.length +
Constants.CHUNK_HEADER_SIZE;
trackerChunks.forEach((trackerChunk: Uint8Array) => { trackerChunks.forEach((trackerChunk: Uint8Array) => {
if ( if (currentInfoPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
currentInfoPacketSize + trackerChunk.length > trackerChunksLists.push(currentTrackerList);
Constants.MAX_UDP_PACKET_SIZE currentTrackerList = [];
) { currentInfoPacketSize = 0;
trackerChunksLists.push(currentTrackerList); }
currentTrackerList = []; currentTrackerList.push(trackerChunk);
currentInfoPacketSize = 0; currentInfoPacketSize += trackerChunk.length;
} });
currentTrackerList.push(trackerChunk); trackerChunksLists.push(currentTrackerList);
currentInfoPacketSize += trackerChunk.length; const header = Encoders.PacketHeaderChunk(
}); timestamp,
trackerChunksLists.push(currentTrackerList); this.versionHigh,
const header = Encoders.PacketHeaderChunk( this.versionLow,
timestamp, frameId ? frameId : this.infoFrameId,
this.versionHigh, trackerChunksLists.length
this.versionLow, );
frameId ? frameId : this.infoFrameId, trackerChunksLists.forEach((trackerChunkList) => {
trackerChunksLists.length infoPackets.push(
); Encoders.InfoPacketChunk(header, systemNameChunk, Encoders.InfoTrackerListChunk(trackerChunkList))
trackerChunksLists.forEach((trackerChunkList) => { );
infoPackets.push( });
Encoders.InfoPacketChunk( this.infoFrameId += 1;
header, if (this.infoFrameId > 255) {
systemNameChunk, this.infoFrameId = 0;
Encoders.InfoTrackerListChunk(trackerChunkList) }
) return infoPackets;
); }
});
this.infoFrameId += 1;
if (this.infoFrameId > 255) {
this.infoFrameId = 0;
}
return infoPackets;
}
getDataPackets(timestamp: bigint, trackers: Tracker[], frameId?: number) { getDataPackets(timestamp: bigint, trackers: Tracker[], frameId?: number) {
if (frameId !== undefined) { if (frameId !== undefined) {
if (!Number.isInteger(frameId)) { if (!Number.isInteger(frameId)) {
throw new Error('frame id must be an integer'); throw new Error('frame id must be an integer');
} }
if (frameId > 255 || frameId < 0) { if (frameId > 255 || frameId < 0) {
throw new Error('frame id must be >= 0 and <= 255'); throw new Error('frame id must be >= 0 and <= 255');
} }
} }
const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk()); const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk());
const dataPackets: Uint8Array[] = []; const dataPackets: Uint8Array[] = [];
const trackerChunksLists: Uint8Array[][] = []; const trackerChunksLists: Uint8Array[][] = [];
let currentTrackerList: Uint8Array[] = []; let currentTrackerList: Uint8Array[] = [];
let currentDataPacketSize = let currentDataPacketSize = Constants.PACKET_HEADER_SIZE + Constants.CHUNK_HEADER_SIZE;
Constants.PACKET_HEADER_SIZE + Constants.CHUNK_HEADER_SIZE;
allTrackerChunks.forEach((trackerChunk) => { allTrackerChunks.forEach((trackerChunk) => {
if ( if (currentDataPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
currentDataPacketSize + trackerChunk.length > trackerChunksLists.push(currentTrackerList);
Constants.MAX_UDP_PACKET_SIZE currentTrackerList = [];
) { currentDataPacketSize = 0;
trackerChunksLists.push(currentTrackerList); }
currentTrackerList = []; currentTrackerList.push(trackerChunk);
currentDataPacketSize = 0; currentDataPacketSize += trackerChunk.length;
} });
currentTrackerList.push(trackerChunk); trackerChunksLists.push(currentTrackerList);
currentDataPacketSize += trackerChunk.length;
});
trackerChunksLists.push(currentTrackerList);
const header = Encoders.PacketHeaderChunk( const header = Encoders.PacketHeaderChunk(
timestamp, timestamp,
this.versionHigh, this.versionHigh,
this.versionLow, this.versionLow,
frameId ? frameId : this.dataFrameId, frameId ? frameId : this.dataFrameId,
trackerChunksLists.length trackerChunksLists.length
); );
trackerChunksLists.forEach((trackerChunks) => { trackerChunksLists.forEach((trackerChunks) => {
dataPackets.push( dataPackets.push(Encoders.DataPacketChunk(header, Encoders.DataTrackerListChunk(trackerChunks)));
Encoders.DataPacketChunk( });
header, this.dataFrameId += 1;
Encoders.DataTrackerListChunk(trackerChunks) if (this.dataFrameId > 255) {
) this.dataFrameId = 0;
); }
}); return dataPackets;
this.dataFrameId += 1; }
if (this.dataFrameId > 255) {
this.dataFrameId = 0;
}
return dataPackets;
}
} }
+19 -23
View File
@@ -1,29 +1,25 @@
const header = new DataView(new ArrayBuffer(4)); export default (id: number, chunkData: Uint8Array, hasSubchunks: boolean): Uint8Array => {
export default ( if (!Number.isInteger(id)) {
id: number, throw new Error('chunk id must be an integer');
chunkData: Uint8Array, }
hasSubchunks: boolean
): Uint8Array => {
if (!Number.isInteger(id)) {
throw new Error('chunk id must be an integer');
}
if (id > 0xffff || id < 0) { if (id > 0xffff || id < 0) {
throw new Error('chunk id must be >= 0 and <= 65535'); throw new Error('chunk id must be >= 0 and <= 65535');
} }
if (chunkData.length > 0x7fff) { if (chunkData.length > 0x7fff) {
throw new Error('chunkData can not be greater than 32767 bytes'); throw new Error('chunkData can not be greater than 32767 bytes');
} }
header.setUint16(0, id, true); const header = new DataView(new ArrayBuffer(4));
const hasSubChunksBit = (hasSubchunks ? 1 : 0) << 15; header.setUint16(0, id, true);
header.setUint16(2, hasSubChunksBit + chunkData.length, true); const hasSubChunksBit = (hasSubchunks ? 1 : 0) << 15;
header.setUint16(2, hasSubChunksBit + chunkData.length, true);
const headerBytes = new Uint8Array(header.buffer); const headerBytes = new Uint8Array(header.buffer);
const bytes = new Uint8Array(headerBytes.length + chunkData.length); const bytes = new Uint8Array(headerBytes.length + chunkData.length);
bytes.set(headerBytes); bytes.set(headerBytes);
bytes.set(chunkData, headerBytes.length); bytes.set(chunkData, headerBytes.length);
return bytes; return bytes;
}; };
+6 -11
View File
@@ -1,12 +1,7 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
export default ( export default (packetHeaderChunk: Uint8Array, trackerListChunk: Uint8Array): Uint8Array => {
packetHeaderChunk: Uint8Array, const chunkData = new Uint8Array(packetHeaderChunk.length + trackerListChunk.length);
trackerListChunk: Uint8Array chunkData.set(packetHeaderChunk);
): Uint8Array => { chunkData.set(trackerListChunk, packetHeaderChunk.length);
const chunkData = new Uint8Array( return chunk(0x6755, chunkData, true);
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.js'; import chunk from '../chunk';
const floatArray = new Float32Array(3);
export default (x: number, y: number, z: number): Uint8Array => { export default (x: number, y: number, z: number): Uint8Array => {
floatArray[0] = x; const buf = new DataView(new ArrayBuffer(12));
floatArray[1] = y; buf.setFloat32(0, x, true);
floatArray[2] = z; buf.setFloat32(4, y, true);
return chunk(0x0004, new Uint8Array(floatArray.buffer), false); buf.setFloat32(8, z, true);
return chunk(0x0004, new Uint8Array(buf.buffer), false);
}; };
+12 -12
View File
@@ -1,20 +1,20 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
export default (trackerId: number, fieldChunks: Uint8Array[]): Uint8Array => { export default (trackerId: number, fieldChunks: Uint8Array[]): Uint8Array => {
let fieldChunksTotalLength = 0; let fieldChunksTotalLength = 0;
fieldChunks.forEach((fieldChunk) => { fieldChunks.forEach((fieldChunk) => {
fieldChunksTotalLength += fieldChunk.length; fieldChunksTotalLength += fieldChunk.length;
}); });
const fieldChunksBytes = new Uint8Array(fieldChunksTotalLength); const fieldChunksBytes = new Uint8Array(fieldChunksTotalLength);
let offset = 0; let offset = 0;
fieldChunks.forEach((fieldChunk) => { fieldChunks.forEach((fieldChunk) => {
fieldChunksBytes.set(fieldChunk, offset); fieldChunksBytes.set(fieldChunk, offset);
offset += fieldChunk.length; offset += fieldChunk.length;
}); });
return chunk(trackerId, fieldChunksBytes, fieldChunks.length > 0); return chunk(trackerId, fieldChunksBytes, fieldChunks.length > 0);
}; };
+12 -12
View File
@@ -1,20 +1,20 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
export default (trackerChunks: Uint8Array[]) => { export default (trackerChunks: Uint8Array[]) => {
let trackerChunksTotalLength = 0; let trackerChunksTotalLength = 0;
trackerChunks.forEach((trackerChunk) => { trackerChunks.forEach((trackerChunk) => {
trackerChunksTotalLength += trackerChunk.length; trackerChunksTotalLength += trackerChunk.length;
}); });
const trackerChunksBytes = new Uint8Array(trackerChunksTotalLength); const trackerChunksBytes = new Uint8Array(trackerChunksTotalLength);
let offset = 0; let offset = 0;
trackerChunks.forEach((trackerChunk) => { trackerChunks.forEach((trackerChunk) => {
trackerChunksBytes.set(trackerChunk, offset); trackerChunksBytes.set(trackerChunk, offset);
offset += trackerChunk.length; offset += trackerChunk.length;
}); });
return chunk(0x0001, trackerChunksBytes, true); return chunk(0x0001, trackerChunksBytes, true);
}; };
+7 -6
View File
@@ -1,9 +1,10 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const floatArray = new Float32Array(3);
export default (x: number, y: number, z: number): Uint8Array => { export default (x: number, y: number, z: number): Uint8Array => {
floatArray[0] = x; const buf = new DataView(new ArrayBuffer(12));
floatArray[1] = y;
floatArray[2] = z; buf.setFloat32(0, x, true);
return chunk(0x0002, new Uint8Array(floatArray.buffer), false); buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0002, new Uint8Array(buf.buffer), false);
}; };
+7 -6
View File
@@ -1,10 +1,11 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const floatArray = new Float32Array(3);
export default (x: number, y: number, z: number): Uint8Array => { export default (x: number, y: number, z: number): Uint8Array => {
floatArray[0] = x; const buf = new DataView(new ArrayBuffer(12));
floatArray[1] = y;
floatArray[2] = z;
return chunk(0x0000, new Uint8Array(floatArray.buffer), false); buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0000, new Uint8Array(buf.buffer), false);
}; };
@@ -1,10 +1,11 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const floatArray = new Float32Array(3);
export default (x: number, y: number, z: number): Uint8Array => { export default (x: number, y: number, z: number): Uint8Array => {
floatArray[0] = x; const buf = new DataView(new ArrayBuffer(12));
floatArray[1] = y;
floatArray[2] = z;
return chunk(0x0001, new Uint8Array(floatArray.buffer), false); 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.js'; import chunk from '../chunk';
const floatArray = new Float32Array(1);
export default (validity: number): Uint8Array => { export default (validity: number): Uint8Array => {
floatArray[0] = validity; const buf = new DataView(new ArrayBuffer(4));
return chunk(0x0003, new Uint8Array(floatArray.buffer), false); buf.setFloat32(0, validity, true);
return chunk(0x0003, new Uint8Array(buf.buffer), false);
}; };
@@ -1,7 +1,7 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const buf = new DataView(new ArrayBuffer(8));
export default (timestamp: bigint): Uint8Array => { export default (timestamp: bigint): Uint8Array => {
buf.setBigUint64(0, BigInt(timestamp), true); const buf = new DataView(new ArrayBuffer(8));
return chunk(0x0006, new Uint8Array(buf.buffer), false); buf.setBigUint64(0, BigInt(timestamp), true);
return chunk(0x0006, new Uint8Array(buf.buffer), false);
}; };
@@ -1,10 +1,11 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const floatArray = new Float32Array(3);
export default (x: number, y: number, z: number): Uint8Array => { export default (x: number, y: number, z: number): Uint8Array => {
floatArray[0] = x; const buf = new DataView(new ArrayBuffer(12));
floatArray[1] = y;
floatArray[2] = z;
return chunk(0x0005, new Uint8Array(floatArray.buffer), false); buf.setFloat32(0, x, true);
buf.setFloat32(4, y, true);
buf.setFloat32(8, z, true);
return chunk(0x0005, new Uint8Array(buf.buffer), false);
}; };
+34 -34
View File
@@ -1,38 +1,38 @@
import Chunk from './chunk.js'; import Chunk from './chunk';
import DataPacketChunk from './data/data-packet-chunk.js'; import DataPacketChunk from './data/data-packet-chunk';
import DataTrackerAccelChunk from './data/data-tracker-accel-chunk.js'; import DataTrackerAccelChunk from './data/data-tracker-accel-chunk';
import DataTrackerChunk from './data/data-tracker-chunk.js'; import DataTrackerChunk from './data/data-tracker-chunk';
import DataTrackerListChunk from './data/data-tracker-list-chunk.js'; import DataTrackerListChunk from './data/data-tracker-list-chunk';
import DataTrackerOriChunk from './data/data-tracker-ori-chunk.js'; import DataTrackerOriChunk from './data/data-tracker-ori-chunk';
import DataTrackerPosChunk from './data/data-tracker-pos-chunk.js'; import DataTrackerPosChunk from './data/data-tracker-pos-chunk';
import DataTrackerSpeedChunk from './data/data-tracker-speed-chunk.js'; import DataTrackerSpeedChunk from './data/data-tracker-speed-chunk';
import DataTrackerStatusChunk from './data/data-tracker-status-chunk.js'; import DataTrackerStatusChunk from './data/data-tracker-status-chunk';
import DataTrackerTimestampChunk from './data/data-tracker-timestamp-chunk.js'; import DataTrackerTimestampChunk from './data/data-tracker-timestamp-chunk';
import DataTrackerTrgtposChunk from './data/data-tracker-trgtpos-chunk.js'; import DataTrackerTrgtposChunk from './data/data-tracker-trgtpos-chunk';
import PacketHeaderChunk from './packet-header-chunk.js'; import PacketHeaderChunk from './packet-header-chunk';
import InfoPacketChunk from './info/info-packet-chunk.js'; import InfoPacketChunk from './info/info-packet-chunk';
import InfoSystemNameChunk from './info/info-system-name-chunk.js'; import InfoSystemNameChunk from './info/info-system-name-chunk';
import InfoTrackerChunk from './info/info-tracker-chunk.js'; import InfoTrackerChunk from './info/info-tracker-chunk';
import InfoTrackerListChunk from './info/info-tracker-list-chunk.js'; import InfoTrackerListChunk from './info/info-tracker-list-chunk';
import InfoTrackerNameChunk from './info/info-tracker-name-chunk.js'; import InfoTrackerNameChunk from './info/info-tracker-name-chunk';
export const Encoders = { export const Encoders = {
DataPacketChunk, DataPacketChunk,
DataTrackerAccelChunk, DataTrackerAccelChunk,
DataTrackerChunk, DataTrackerChunk,
DataTrackerListChunk, DataTrackerListChunk,
DataTrackerOriChunk, DataTrackerOriChunk,
DataTrackerPosChunk, DataTrackerPosChunk,
DataTrackerSpeedChunk, DataTrackerSpeedChunk,
DataTrackerStatusChunk, DataTrackerStatusChunk,
DataTrackerTimestampChunk, DataTrackerTimestampChunk,
DataTrackerTrgtposChunk, DataTrackerTrgtposChunk,
InfoPacketChunk, InfoPacketChunk,
InfoSystemNameChunk, InfoSystemNameChunk,
InfoTrackerChunk, InfoTrackerChunk,
InfoTrackerListChunk, InfoTrackerListChunk,
InfoTrackerNameChunk, InfoTrackerNameChunk,
PacketHeaderChunk, PacketHeaderChunk,
Chunk, Chunk,
}; };
+9 -14
View File
@@ -1,19 +1,14 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
export default ( export default (
packetHeaderChunk: Uint8Array, packetHeaderChunk: Uint8Array,
systemNameChunk: Uint8Array, systemNameChunk: Uint8Array,
trackerListChunk: Uint8Array trackerListChunk: Uint8Array
): Uint8Array => { ): Uint8Array => {
const chunkData = new Uint8Array( const chunkData = new Uint8Array(packetHeaderChunk.length + systemNameChunk.length + trackerListChunk.length);
packetHeaderChunk.length + systemNameChunk.length + trackerListChunk.length
);
chunkData.set(packetHeaderChunk); chunkData.set(packetHeaderChunk);
chunkData.set(systemNameChunk, packetHeaderChunk.length); chunkData.set(systemNameChunk, packetHeaderChunk.length);
chunkData.set( chunkData.set(trackerListChunk, packetHeaderChunk.length + systemNameChunk.length);
trackerListChunk, return chunk(0x6756, chunkData, true);
packetHeaderChunk.length + systemNameChunk.length
);
return chunk(0x6756, chunkData, true);
}; };
+3 -4
View File
@@ -1,4 +1,3 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const nameEncoder = new TextEncoder();
export default (systemName: string): Uint8Array => export default (systemName: string): Uint8Array => chunk(0x0001, new TextEncoder().encode(systemName), false);
chunk(0x0001, nameEncoder.encode(systemName), false);
+2 -2
View File
@@ -1,4 +1,4 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
export default (trackerId: number, trackerNameChunk: Uint8Array): Uint8Array => export default (trackerId: number, trackerNameChunk: Uint8Array): Uint8Array =>
chunk(trackerId, trackerNameChunk, true); chunk(trackerId, trackerNameChunk, true);
+12 -12
View File
@@ -1,19 +1,19 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
export default (trackerChunks: Uint8Array[]): Uint8Array => { export default (trackerChunks: Uint8Array[]): Uint8Array => {
let trackerChunksTotalLength = 0; let trackerChunksTotalLength = 0;
trackerChunks.forEach((trackerChunk) => { trackerChunks.forEach((trackerChunk) => {
trackerChunksTotalLength += trackerChunk.length; trackerChunksTotalLength += trackerChunk.length;
}); });
const trackerChunksBytes = new Uint8Array(trackerChunksTotalLength); const trackerChunksBytes = new Uint8Array(trackerChunksTotalLength);
let offset = 0; let offset = 0;
trackerChunks.forEach((trackerChunk) => { trackerChunks.forEach((trackerChunk) => {
trackerChunksBytes.set(trackerChunk, offset); trackerChunksBytes.set(trackerChunk, offset);
offset += trackerChunk.length; offset += trackerChunk.length;
}); });
return chunk(0x0002, trackerChunksBytes, true); return chunk(0x0002, trackerChunksBytes, true);
}; };
+2 -4
View File
@@ -1,5 +1,3 @@
import chunk from '../chunk.js'; import chunk from '../chunk';
const nameEncoder = new TextEncoder(); export default (trackerName: string) => chunk(0x0000, new TextEncoder().encode(trackerName), false);
export default (trackerName: string) =>
chunk(0x0000, nameEncoder.encode(trackerName), false);
+37 -37
View File
@@ -1,44 +1,44 @@
import chunk from './chunk.js'; import chunk from './chunk';
const packetHeader = new DataView(new ArrayBuffer(12));
export default ( export default (
timestamp: bigint, timestamp: bigint,
versionHigh: number, versionHigh: number,
versionLow: number, versionLow: number,
frameId: number, frameId: number,
framePacketCount: number framePacketCount: number
): Uint8Array => { ): Uint8Array => {
if (!Number.isInteger(versionHigh)) { if (!Number.isInteger(versionHigh)) {
throw new Error('version high must be an integer'); throw new Error('version high must be an integer');
} }
if (!Number.isInteger(versionLow)) { if (!Number.isInteger(versionLow)) {
throw new Error('version low must be an integer'); throw new Error('version low must be an integer');
} }
if (!Number.isInteger(frameId)) { if (!Number.isInteger(frameId)) {
throw new Error('frame id must be an integer'); throw new Error('frame id must be an integer');
} }
if (!Number.isInteger(framePacketCount)) { if (!Number.isInteger(framePacketCount)) {
throw new Error('frame packet count must be an integer'); throw new Error('frame packet count must be an integer');
} }
if (versionHigh > 255 || versionHigh < 0) { if (versionHigh > 255 || versionHigh < 0) {
throw new Error('version high must be >= 0 and <= 255'); throw new Error('version high must be >= 0 and <= 255');
} }
if (versionLow > 255 || versionLow < 0) { if (versionLow > 255 || versionLow < 0) {
throw new Error('version low must be >= 0 and <= 255'); throw new Error('version low must be >= 0 and <= 255');
} }
if (frameId > 255 || frameId < 0) { if (frameId > 255 || frameId < 0) {
throw new Error('frame id must be >= 0 and <= 255'); throw new Error('frame id must be >= 0 and <= 255');
} }
if (framePacketCount > 255 || framePacketCount < 0) { if (framePacketCount > 255 || framePacketCount < 0) {
throw new Error('frame packet count must be >= 0 and <= 255'); throw new Error('frame packet count must be >= 0 and <= 255');
} }
packetHeader.setBigUint64(0, BigInt(timestamp), true); const packetHeader = new DataView(new ArrayBuffer(12));
packetHeader.setUint8(8, versionHigh); packetHeader.setBigUint64(0, BigInt(timestamp), true);
packetHeader.setUint8(9, versionLow); packetHeader.setUint8(8, versionHigh);
packetHeader.setUint8(10, frameId); packetHeader.setUint8(9, versionLow);
packetHeader.setUint8(11, framePacketCount); packetHeader.setUint8(10, frameId);
packetHeader.setUint8(11, framePacketCount);
return chunk(0x0000, new Uint8Array(packetHeader.buffer), false); return chunk(0x0000, new Uint8Array(packetHeader.buffer), false);
}; };
+5 -5
View File
@@ -1,5 +1,5 @@
export { Decoder } from './decoder.js'; export { Decoder } from './decoder';
export * from './decoders/index.js'; export * from './decoders';
export { Encoder } from './encoder.js'; export { Encoder } from './encoder';
export * from './encoders/index.js'; export * from './encoders';
export * from './models/index.js'; export * from './models';
+5 -5
View File
@@ -1,10 +1,10 @@
export interface ChunkHeader { export interface ChunkHeader {
id: number; id: number;
dataLen: number; dataLen: number;
hasSubchunks: boolean; hasSubchunks: boolean;
} }
export interface Chunk { export interface Chunk {
chunkData: Uint8Array; chunkData: Uint8Array;
header: ChunkHeader; header: ChunkHeader;
} }
+7 -7
View File
@@ -1,13 +1,13 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
import type { PacketHeaderChunk } from '../packet-header-chunk.js'; import { PacketHeaderChunk } from '../packet-header-chunk';
import type { DataTrackerListChunk } from './data-tracker-list-chunk.js'; import { DataTrackerListChunk } from './data-tracker-list-chunk';
export interface DataPacketChunkData { export interface DataPacketChunkData {
packetHeader?: PacketHeaderChunk; packetHeader?: PacketHeaderChunk;
trackerList?: DataTrackerListChunk; trackerList?: DataTrackerListChunk;
} }
export interface DataPacketChunk { export interface DataPacketChunk {
chunk: Chunk; chunk: Chunk;
data: DataPacketChunkData; data: DataPacketChunkData;
} }
+13 -13
View File
@@ -1,19 +1,19 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
import type { DataTrackerStatusChunk } from './data-tracker-status-chunk.js'; import { DataTrackerStatusChunk } from './data-tracker-status-chunk';
import type { DataTrackerTimestampChunk } from './data-tracker-timestamp-chunk.js'; import { DataTrackerTimestampChunk } from './data-tracker-timestamp-chunk';
import type { DataTrackerXYZChunk } from './data-tracker-xyz-chunk.js'; import { DataTrackerXYZChunk } from './data-tracker-xyz-chunk';
export interface DataTrackerChunkData { export interface DataTrackerChunkData {
pos?: DataTrackerXYZChunk; pos?: DataTrackerXYZChunk;
speed?: DataTrackerXYZChunk; speed?: DataTrackerXYZChunk;
ori?: DataTrackerXYZChunk; ori?: DataTrackerXYZChunk;
status?: DataTrackerStatusChunk; status?: DataTrackerStatusChunk;
accel?: DataTrackerXYZChunk; accel?: DataTrackerXYZChunk;
trgtpos?: DataTrackerXYZChunk; trgtpos?: DataTrackerXYZChunk;
timestamp?: DataTrackerTimestampChunk; timestamp?: DataTrackerTimestampChunk;
} }
export interface DataTrackerChunk { export interface DataTrackerChunk {
chunk: Chunk; chunk: Chunk;
data: DataTrackerChunkData; data: DataTrackerChunkData;
} }
+5 -5
View File
@@ -1,11 +1,11 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
import type { DataTrackerChunk } from './data-tracker-chunk.js'; import { DataTrackerChunk } from './data-tracker-chunk';
export interface DataTrackerListChunkData { export interface DataTrackerListChunkData {
trackers: DataTrackerChunk[]; trackers: DataTrackerChunk[];
} }
export interface DataTrackerListChunk { export interface DataTrackerListChunk {
chunk: Chunk; chunk: Chunk;
data: DataTrackerListChunkData; data: DataTrackerListChunkData;
} }
+4 -4
View File
@@ -1,10 +1,10 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
export interface DataTrackerStatusChunkData { export interface DataTrackerStatusChunkData {
validity: number; validity: number;
} }
export interface DataTrackerStatusChunk { export interface DataTrackerStatusChunk {
chunk: Chunk; chunk: Chunk;
data: DataTrackerStatusChunkData; data: DataTrackerStatusChunkData;
} }
@@ -1,10 +1,10 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
export interface DataTrackerTimestampChunkData { export interface DataTrackerTimestampChunkData {
timestamp: bigint; timestamp: bigint;
} }
export interface DataTrackerTimestampChunk { export interface DataTrackerTimestampChunk {
chunk: Chunk; chunk: Chunk;
data: DataTrackerTimestampChunkData; data: DataTrackerTimestampChunkData;
} }
+6 -6
View File
@@ -1,12 +1,12 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
export interface DataTrackerXYZChunkData { export interface DataTrackerXYZChunkData {
x: number; x: number;
y: number; y: number;
z: number; z: number;
} }
export interface DataTrackerXYZChunk { export interface DataTrackerXYZChunk {
chunk: Chunk; chunk: Chunk;
data: DataTrackerXYZChunkData; data: DataTrackerXYZChunkData;
} }
+11 -11
View File
@@ -1,11 +1,11 @@
export * from './chunk.js'; export * from './chunk';
export * from './data/data-packet-chunk.js'; export * from './data/data-packet-chunk';
export * from './data/data-tracker-chunk.js'; export * from './data/data-tracker-chunk';
export * from './data/data-tracker-list-chunk.js'; export * from './data/data-tracker-list-chunk';
export * from './info/info-packet-chunk.js'; export * from './info/info-packet-chunk';
export * from './info/info-system-name-chunk.js'; export * from './info/info-system-name-chunk';
export * from './info/info-tracker-chunk.js'; export * from './info/info-tracker-chunk';
export * from './info/info-tracker-list-chunk.js'; export * from './info/info-tracker-list-chunk';
export * from './info/info-tracker-name-chunk.js'; export * from './info/info-tracker-name-chunk';
export * from './packet-header-chunk.js'; export * from './packet-header-chunk';
export * from './tracker.js'; export * from './tracker';
+9 -9
View File
@@ -1,14 +1,14 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
import type { PacketHeaderChunk } from '../packet-header-chunk.js'; import { PacketHeaderChunk } from '../packet-header-chunk';
import type { InfoSystemNameChunk } from './info-system-name-chunk.js'; import { InfoSystemNameChunk } from './info-system-name-chunk';
import type { InfoTrackerListChunk } from './info-tracker-list-chunk.js'; import { InfoTrackerListChunk } from './info-tracker-list-chunk';
export interface InfoPacketChunkData { export interface InfoPacketChunkData {
packetHeader?: PacketHeaderChunk; packetHeader?: PacketHeaderChunk;
systemName?: InfoSystemNameChunk; systemName?: InfoSystemNameChunk;
trackerList?: InfoTrackerListChunk; trackerList?: InfoTrackerListChunk;
} }
export interface InfoPacketChunk { export interface InfoPacketChunk {
chunk: Chunk; chunk: Chunk;
data: InfoPacketChunkData; data: InfoPacketChunkData;
} }
+4 -4
View File
@@ -1,10 +1,10 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
export interface InfoSystemNameChunkData { export interface InfoSystemNameChunkData {
systemName: string; systemName: string;
} }
export interface InfoSystemNameChunk { export interface InfoSystemNameChunk {
chunk: Chunk; chunk: Chunk;
data: InfoSystemNameChunkData; data: InfoSystemNameChunkData;
} }
+5 -5
View File
@@ -1,11 +1,11 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
import type { InfoTrackerNameChunk } from './info-tracker-name-chunk.js'; import { InfoTrackerNameChunk } from './info-tracker-name-chunk';
export interface InfoTrackerChunkData { export interface InfoTrackerChunkData {
trackerName: InfoTrackerNameChunk; trackerName: InfoTrackerNameChunk;
} }
export interface InfoTrackerChunk { export interface InfoTrackerChunk {
chunk: Chunk; chunk: Chunk;
data?: InfoTrackerChunkData; data?: InfoTrackerChunkData;
} }
+5 -5
View File
@@ -1,11 +1,11 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
import type { InfoTrackerChunk } from './info-tracker-chunk.js'; import { InfoTrackerChunk } from './info-tracker-chunk';
export interface InfoTrackerListChunkData { export interface InfoTrackerListChunkData {
trackers: InfoTrackerChunk[]; trackers: InfoTrackerChunk[];
} }
export interface InfoTrackerListChunk { export interface InfoTrackerListChunk {
chunk: Chunk; chunk: Chunk;
data: InfoTrackerListChunkData; data: InfoTrackerListChunkData;
} }
+4 -4
View File
@@ -1,10 +1,10 @@
import type { Chunk } from '../chunk.js'; import { Chunk } from '../chunk';
export interface InfoTrackerNameChunkData { export interface InfoTrackerNameChunkData {
trackerName: string; trackerName: string;
} }
export interface InfoTrackerNameChunk { export interface InfoTrackerNameChunk {
chunk: Chunk; chunk: Chunk;
data: InfoTrackerNameChunkData; data: InfoTrackerNameChunkData;
} }
+8 -8
View File
@@ -1,14 +1,14 @@
import type { Chunk } from './chunk.js'; import { Chunk } from './chunk';
export interface PacketHeaderChunkData { export interface PacketHeaderChunkData {
packetTimestamp: bigint; packetTimestamp: bigint;
versionHigh: number; versionHigh: number;
versionLow: number; versionLow: number;
frameId: number; frameId: number;
framePacketCount: number; framePacketCount: number;
} }
export interface PacketHeaderChunk { export interface PacketHeaderChunk {
chunk: Chunk; chunk: Chunk;
data: PacketHeaderChunkData; data: PacketHeaderChunkData;
} }
+184 -201
View File
@@ -1,239 +1,222 @@
import dataTrackerAccelChunk from '../encoders/data/data-tracker-accel-chunk.js'; import dataTrackerAccelChunk from '../encoders/data/data-tracker-accel-chunk';
import dataTrackerChunk from '../encoders/data/data-tracker-chunk.js'; import dataTrackerChunk from '../encoders/data/data-tracker-chunk';
import dataTrackerOriChunk from '../encoders/data/data-tracker-ori-chunk.js'; import dataTrackerOriChunk from '../encoders/data/data-tracker-ori-chunk';
import dataTrackerPosChunk from '../encoders/data/data-tracker-pos-chunk.js'; import dataTrackerPosChunk from '../encoders/data/data-tracker-pos-chunk';
import dataTrackerSpeedChunk from '../encoders/data/data-tracker-speed-chunk.js'; import dataTrackerSpeedChunk from '../encoders/data/data-tracker-speed-chunk';
import dataTrackerStatusChunk from '../encoders/data/data-tracker-status-chunk.js'; import dataTrackerStatusChunk from '../encoders/data/data-tracker-status-chunk';
import dataTrackerTimestampChunk from '../encoders/data/data-tracker-timestamp-chunk.js'; import dataTrackerTimestampChunk from '../encoders/data/data-tracker-timestamp-chunk';
import dataTrackerTrgtposChunk from '../encoders/data/data-tracker-trgtpos-chunk.js'; import dataTrackerTrgtposChunk from '../encoders/data/data-tracker-trgtpos-chunk';
import infoTrackerChunk from '../encoders/info/info-tracker-chunk.js'; import infoTrackerChunk from '../encoders/info/info-tracker-chunk';
import infoTrackerNameChunk from '../encoders/info/info-tracker-name-chunk.js'; import infoTrackerNameChunk from '../encoders/info/info-tracker-name-chunk';
import type { DataTrackerChunk } from './data/data-tracker-chunk.js'; import { DataTrackerChunk } from './data/data-tracker-chunk';
import type { InfoTrackerChunk } from './info/info-tracker-chunk.js'; import { InfoTrackerChunk } from './info/info-tracker-chunk';
export type XYZData = { export type XYZData = {
x: number; x: number;
y: number; y: number;
z: number; z: number;
}; };
export class Tracker { export class Tracker {
id: number; id: number;
name: string; name: string;
pos?: XYZData; pos?: XYZData;
speed?: XYZData; speed?: XYZData;
ori?: XYZData; ori?: XYZData;
validity?: number; validity?: number;
accel?: XYZData; accel?: XYZData;
trgtpos?: XYZData; trgtpos?: XYZData;
timestamp?: bigint; timestamp?: bigint;
constructor(id: number, name: string) { constructor(id: number, name: string) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.pos = undefined; this.pos = undefined;
this.speed = undefined; this.speed = undefined;
this.ori = undefined; this.ori = undefined;
this.validity = undefined; this.validity = undefined;
this.accel = undefined; this.accel = undefined;
this.trgtpos = undefined; this.trgtpos = undefined;
this.timestamp = undefined; this.timestamp = undefined;
} }
setPos(x: number, y: number, z: number) { setPos(x: number, y: number, z: number) {
if (this.pos === undefined) { if (this.pos === undefined) {
this.pos = { this.pos = {
x, x,
y, y,
z, z,
}; };
} else { } else {
this.pos.x = x; this.pos.x = x;
this.pos.y = y; this.pos.y = y;
this.pos.z = z; this.pos.z = z;
} }
} }
setSpeed(x: number, y: number, z: number) { setSpeed(x: number, y: number, z: number) {
if (this.speed === undefined) { if (this.speed === undefined) {
this.speed = { this.speed = {
x, x,
y, y,
z, z,
}; };
} else { } else {
this.speed.x = x; this.speed.x = x;
this.speed.y = y; this.speed.y = y;
this.speed.z = z; this.speed.z = z;
} }
} }
setOri(x: number, y: number, z: number) { setOri(x: number, y: number, z: number) {
if (this.ori === undefined) { if (this.ori === undefined) {
this.ori = { this.ori = {
x, x,
y, y,
z, z,
}; };
} else { } else {
this.ori.x = x; this.ori.x = x;
this.ori.y = y; this.ori.y = y;
this.ori.z = z; this.ori.z = z;
} }
} }
setStatus(validity: number) { setStatus(validity: number) {
this.validity = validity; this.validity = validity;
} }
setAccel(x: number, y: number, z: number) { setAccel(x: number, y: number, z: number) {
if (this.accel === undefined) { if (this.accel === undefined) {
this.accel = { this.accel = {
x, x,
y, y,
z, z,
}; };
} else { } else {
this.accel.x = x; this.accel.x = x;
this.accel.y = y; this.accel.y = y;
this.accel.z = z; this.accel.z = z;
} }
} }
setTrgtPos(x: number, y: number, z: number) { setTrgtPos(x: number, y: number, z: number) {
if (this.trgtpos === undefined) { if (this.trgtpos === undefined) {
this.trgtpos = { this.trgtpos = {
x, x,
y, y,
z, z,
}; };
} else { } else {
this.trgtpos.x = x; this.trgtpos.x = x;
this.trgtpos.y = y; this.trgtpos.y = y;
this.trgtpos.z = z; this.trgtpos.z = z;
} }
} }
setTimestamp(timestamp: bigint) { setTimestamp(timestamp: bigint) {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
getDataChunk() { getDataChunk() {
const fieldChunks: Uint8Array[] = []; const fieldChunks: Uint8Array[] = [];
if (this.pos) { if (this.pos) {
fieldChunks.push(dataTrackerPosChunk(this.pos.x, this.pos.y, this.pos.z)); fieldChunks.push(dataTrackerPosChunk(this.pos.x, this.pos.y, this.pos.z));
} }
if (this.speed) { if (this.speed) {
fieldChunks.push( fieldChunks.push(dataTrackerSpeedChunk(this.speed.x, this.speed.y, this.speed.z));
dataTrackerSpeedChunk(this.speed.x, this.speed.y, this.speed.z) }
);
}
if (this.ori) { if (this.ori) {
fieldChunks.push(dataTrackerOriChunk(this.ori.x, this.ori.y, this.ori.z)); fieldChunks.push(dataTrackerOriChunk(this.ori.x, this.ori.y, this.ori.z));
} }
if (this.validity) { if (this.validity) {
fieldChunks.push(dataTrackerStatusChunk(this.validity)); fieldChunks.push(dataTrackerStatusChunk(this.validity));
} }
if (this.accel) { if (this.accel) {
fieldChunks.push( fieldChunks.push(dataTrackerAccelChunk(this.accel.x, this.accel.y, this.accel.z));
dataTrackerAccelChunk(this.accel.x, this.accel.y, this.accel.z) }
);
}
if (this.trgtpos) { if (this.trgtpos) {
fieldChunks.push( fieldChunks.push(dataTrackerTrgtposChunk(this.trgtpos.x, this.trgtpos.y, this.trgtpos.z));
dataTrackerTrgtposChunk(this.trgtpos.x, this.trgtpos.y, this.trgtpos.z) }
);
}
if (this.timestamp) { if (this.timestamp) {
fieldChunks.push(dataTrackerTimestampChunk(this.timestamp)); fieldChunks.push(dataTrackerTimestampChunk(this.timestamp));
} }
return dataTrackerChunk(this.id, fieldChunks); return dataTrackerChunk(this.id, fieldChunks);
} }
getInfoChunk() { getInfoChunk() {
return infoTrackerChunk(this.id, infoTrackerNameChunk(this.name)); return infoTrackerChunk(this.id, infoTrackerNameChunk(this.name));
} }
updateInfo(infoTrackerChunk: InfoTrackerChunk) { updateInfo(infoTrackerChunk: InfoTrackerChunk) {
if (infoTrackerChunk.data) { if (infoTrackerChunk.data) {
this.name = infoTrackerChunk.data.trackerName.data.trackerName; this.name = infoTrackerChunk.data.trackerName.data.trackerName;
} }
} }
updateData(dataTrackerChunk: DataTrackerChunk) { updateData(dataTrackerChunk: DataTrackerChunk) {
if (dataTrackerChunk.data.pos) { if (dataTrackerChunk.data.pos) {
this.setPos( this.setPos(dataTrackerChunk.data.pos.data.x, dataTrackerChunk.data.pos.data.y, dataTrackerChunk.data.pos.data.z);
dataTrackerChunk.data.pos.data.x, }
dataTrackerChunk.data.pos.data.y,
dataTrackerChunk.data.pos.data.z
);
}
if (dataTrackerChunk.data.speed) { if (dataTrackerChunk.data.speed) {
this.setSpeed( this.setSpeed(
dataTrackerChunk.data.speed.data.x, dataTrackerChunk.data.speed.data.x,
dataTrackerChunk.data.speed.data.y, dataTrackerChunk.data.speed.data.y,
dataTrackerChunk.data.speed.data.z dataTrackerChunk.data.speed.data.z
); );
} }
if (dataTrackerChunk.data.ori) { if (dataTrackerChunk.data.ori) {
this.setOri( this.setOri(dataTrackerChunk.data.ori.data.x, dataTrackerChunk.data.ori.data.y, dataTrackerChunk.data.ori.data.z);
dataTrackerChunk.data.ori.data.x, }
dataTrackerChunk.data.ori.data.y,
dataTrackerChunk.data.ori.data.z
);
}
if (dataTrackerChunk.data.status) { if (dataTrackerChunk.data.status) {
this.setStatus(dataTrackerChunk.data.status.data.validity); this.setStatus(dataTrackerChunk.data.status.data.validity);
} }
if (dataTrackerChunk.data.accel) { if (dataTrackerChunk.data.accel) {
this.setAccel( this.setAccel(
dataTrackerChunk.data.accel.data.x, dataTrackerChunk.data.accel.data.x,
dataTrackerChunk.data.accel.data.y, dataTrackerChunk.data.accel.data.y,
dataTrackerChunk.data.accel.data.z dataTrackerChunk.data.accel.data.z
); );
} }
if (dataTrackerChunk.data.trgtpos) { if (dataTrackerChunk.data.trgtpos) {
this.setTrgtPos( this.setTrgtPos(
dataTrackerChunk.data.trgtpos.data.x, dataTrackerChunk.data.trgtpos.data.x,
dataTrackerChunk.data.trgtpos.data.y, dataTrackerChunk.data.trgtpos.data.y,
dataTrackerChunk.data.trgtpos.data.z dataTrackerChunk.data.trgtpos.data.z
); );
} }
if (dataTrackerChunk.data.timestamp) { if (dataTrackerChunk.data.timestamp) {
this.setTimestamp(dataTrackerChunk.data.timestamp.data.timestamp); this.setTimestamp(dataTrackerChunk.data.timestamp.data.timestamp);
} }
} }
} }
export function TrackerFromInfo(infoTrackerChunk: InfoTrackerChunk) { export function TrackerFromInfo(infoTrackerChunk: InfoTrackerChunk) {
if (infoTrackerChunk.data) { if (infoTrackerChunk.data) {
return new Tracker( return new Tracker(infoTrackerChunk.chunk.header.id, infoTrackerChunk.data.trackerName.data.trackerName);
infoTrackerChunk.chunk.header.id, }
infoTrackerChunk.data.trackerName.data.trackerName return undefined;
);
}
return undefined;
} }
export function TrackerFromData(dataTrackerChunk: DataTrackerChunk) { export function TrackerFromData(dataTrackerChunk: DataTrackerChunk) {
if (dataTrackerChunk.data) { if (dataTrackerChunk.data) {
const tracker = new Tracker(dataTrackerChunk.chunk.header.id, ''); const tracker = new Tracker(dataTrackerChunk.chunk.header.id, '');
tracker.updateData(dataTrackerChunk); tracker.updateData(dataTrackerChunk);
return tracker; return tracker;
} }
return undefined; return undefined;
} }
-738
View File
@@ -1,738 +0,0 @@
import { Decoders } from '@jwetzell/posistagenet';
import { deepEqual, throws } from 'node:assert';
import { describe, it } from 'node:test';
const goodTests = [
{
description: 'DataTrackerPosChunk',
bytes: new Uint8Array([
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
expected: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
decoder: Decoders.DataTrackerXYZChunk,
},
{
description: 'DataTrackerSpeedChunk',
bytes: new Uint8Array([
1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
expected: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
header: { dataLen: 12, id: 1, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
decoder: Decoders.DataTrackerXYZChunk,
},
{
description: 'DataTrackerOriChunk',
bytes: new Uint8Array([
2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
expected: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
header: { dataLen: 12, id: 2, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
decoder: Decoders.DataTrackerXYZChunk,
},
{
description: 'DataTrackerStatusChunk',
bytes: new Uint8Array([3, 0, 4, 0, 0, 0, 128, 63]),
expected: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63]),
header: { dataLen: 4, id: 3, hasSubchunks: false },
},
data: {
validity: 1.0,
},
},
decoder: Decoders.DataTrackerStatusChunk,
},
{
description: 'DataTrackerAccelChunk',
bytes: new Uint8Array([
4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
expected: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
header: { dataLen: 12, id: 4, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
decoder: Decoders.DataTrackerXYZChunk,
},
{
description: 'DataTrackerTrgtPosChunk',
bytes: new Uint8Array([
5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
expected: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
header: { dataLen: 12, id: 5, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
decoder: Decoders.DataTrackerXYZChunk,
},
{
description: 'DataTrackerTimestampChunk',
bytes: new Uint8Array([6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0]),
expected: {
chunk: {
chunkData: new Uint8Array([210, 2, 150, 73, 0, 0, 0, 0]),
header: { dataLen: 8, id: 6, hasSubchunks: false },
},
data: {
timestamp: 1234567890n,
},
},
decoder: Decoders.DataTrackerTimestampChunk,
},
{
description: 'DataTrackerChunk',
bytes: new Uint8Array([
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1,
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0,
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12,
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63,
0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0, 128, 63, 0,
0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12, 0, 0, 0,
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0,
0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
]),
header: { dataLen: 100, id: 1, hasSubchunks: true },
},
data: {
pos: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
speed: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 1, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
ori: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 2, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
status: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63]),
header: { dataLen: 4, id: 3, hasSubchunks: false },
},
data: {
validity: 1.0,
},
},
accel: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 4, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
trgtpos: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 5, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
timestamp: {
chunk: {
chunkData: new Uint8Array([210, 2, 150, 73, 0, 0, 0, 0]),
header: { dataLen: 8, id: 6, hasSubchunks: false },
},
data: {
timestamp: 1234567890n,
},
},
},
},
decoder: Decoders.DataTrackerChunk,
},
{
description: 'DataTrackerListChunk',
bytes: new Uint8Array([
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128,
63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0,
0, 0,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4,
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0,
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0,
0, 0,
]),
header: { dataLen: 104, id: 1, hasSubchunks: true },
},
data: {
trackers: [
{
chunk: {
chunkData: new Uint8Array([
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0, 12,
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0,
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63,
4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12,
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2,
150, 73, 0, 0, 0, 0,
]),
header: { dataLen: 100, id: 1, hasSubchunks: true },
},
data: {
pos: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
speed: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 1, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
ori: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 2, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
status: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63]),
header: { dataLen: 4, id: 3, hasSubchunks: false },
},
data: {
validity: 1.0,
},
},
accel: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 4, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
trgtpos: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 5, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
timestamp: {
chunk: {
chunkData: new Uint8Array([210, 2, 150, 73, 0, 0, 0, 0]),
header: { dataLen: 8, id: 6, hasSubchunks: false },
},
data: {
timestamp: 1234567890n,
},
},
},
},
],
},
},
decoder: Decoders.DataTrackerListChunk,
},
{
description: 'DataPacketChunk',
bytes: new Uint8Array([
85, 103, 124, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128,
63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0,
0, 0,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 104,
128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0,
64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0,
128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2,
150, 73, 0, 0, 0, 0,
]),
header: { dataLen: 124, id: 26453, hasSubchunks: true },
},
data: {
packetHeader: {
chunk: {
chunkData: new Uint8Array([
210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
packetTimestamp: 1234567890n,
versionHigh: 2,
versionLow: 3,
frameId: 1,
framePacketCount: 123,
},
},
trackerList: {
chunk: {
chunkData: new Uint8Array([
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0,
128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5,
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0,
210, 2, 150, 73, 0, 0, 0, 0,
]),
header: { dataLen: 104, id: 1, hasSubchunks: true },
},
data: {
trackers: [
{
chunk: {
chunkData: new Uint8Array([
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12,
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0,
0, 128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0,
64, 64, 5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64,
64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
]),
header: { dataLen: 100, id: 1, hasSubchunks: true },
},
data: {
pos: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
speed: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 1, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
ori: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 2, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
status: {
chunk: {
chunkData: new Uint8Array([0, 0, 128, 63]),
header: { dataLen: 4, id: 3, hasSubchunks: false },
},
data: {
validity: 1.0,
},
},
accel: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 4, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
trgtpos: {
chunk: {
chunkData: new Uint8Array([
0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
header: { dataLen: 12, id: 5, hasSubchunks: false },
},
data: {
x: 1.0,
y: 2.0,
z: 3.0,
},
},
timestamp: {
chunk: {
chunkData: new Uint8Array([210, 2, 150, 73, 0, 0, 0, 0]),
header: { dataLen: 8, id: 6, hasSubchunks: false },
},
data: {
timestamp: 1234567890n,
},
},
},
},
],
},
},
},
},
decoder: Decoders.DataPacketChunk,
},
{
description: 'InfoTrackerNameChunk',
bytes: new Uint8Array([0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49]),
expected: {
chunk: {
chunkData: new Uint8Array([84, 114, 97, 99, 107, 101, 114, 32, 49]),
header: { dataLen: 9, id: 0, hasSubchunks: false },
},
data: {
trackerName: 'Tracker 1',
},
},
decoder: Decoders.InfoTrackerNameChunk,
},
{
description: 'InfoSystemNameChunk',
bytes: new Uint8Array([
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
]),
header: { dataLen: 10, id: 1, hasSubchunks: false },
},
data: {
systemName: 'PSN Server',
},
},
decoder: Decoders.InfoSystemNameChunk,
},
{
description: 'InfoTrackerChunk',
bytes: new Uint8Array([
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 13, id: 1, hasSubchunks: true },
},
data: {
trackerName: {
chunk: {
chunkData: new Uint8Array([84, 114, 97, 99, 107, 101, 114, 32, 49]),
header: { dataLen: 9, id: 0, hasSubchunks: false },
},
data: {
trackerName: 'Tracker 1',
},
},
},
},
decoder: Decoders.InfoTrackerChunk,
},
{
description: 'InfoTrackerListChunk',
bytes: new Uint8Array([
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114,
32, 49,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 17, id: 2, hasSubchunks: true },
},
data: {
trackers: [
{
chunk: {
chunkData: new Uint8Array([
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 13, id: 1, hasSubchunks: true },
},
data: {
trackerName: {
chunk: {
chunkData: new Uint8Array([
84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 9, id: 0, hasSubchunks: false },
},
data: {
trackerName: 'Tracker 1',
},
},
},
},
],
},
},
decoder: Decoders.InfoTrackerListChunk,
},
{
description: 'PacketHeaderChunk',
bytes: new Uint8Array([
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
]),
expected: {
chunk: {
chunkData: new Uint8Array([210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
packetTimestamp: 1234567890n,
versionHigh: 2,
versionLow: 3,
frameId: 1,
framePacketCount: 123,
},
},
decoder: Decoders.PacketHeaderChunk,
},
{
description: 'InfoPacketChunk',
bytes: new Uint8Array([
86, 103, 51, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114, 2, 0, 17, 128,
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
expected: {
chunk: {
chunkData: new Uint8Array([
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123, 1, 0, 10, 0,
80, 83, 78, 32, 83, 101, 114, 118, 101, 114, 2, 0, 17, 128, 1, 0, 13,
128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 51, id: 26454, hasSubchunks: true },
},
data: {
packetHeader: {
chunk: {
chunkData: new Uint8Array([
210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
]),
header: { dataLen: 12, id: 0, hasSubchunks: false },
},
data: {
packetTimestamp: 1234567890n,
versionHigh: 2,
versionLow: 3,
frameId: 1,
framePacketCount: 123,
},
},
systemName: {
chunk: {
chunkData: new Uint8Array([
80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
]),
header: { dataLen: 10, id: 1, hasSubchunks: false },
},
data: {
systemName: 'PSN Server',
},
},
trackerList: {
chunk: {
chunkData: new Uint8Array([
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 17, id: 2, hasSubchunks: true },
},
data: {
trackers: [
{
chunk: {
chunkData: new Uint8Array([
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 13, id: 1, hasSubchunks: true },
},
data: {
trackerName: {
chunk: {
chunkData: new Uint8Array([
84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
header: { dataLen: 9, id: 0, hasSubchunks: false },
},
data: {
trackerName: 'Tracker 1',
},
},
},
},
],
},
},
},
},
decoder: Decoders.InfoPacketChunk,
},
];
describe('PSN Bytes Decoding', () => {
goodTests.forEach((bytesTest) => {
it(bytesTest.description, () => {
const decoded = bytesTest.decoder(bytesTest.bytes);
deepEqual(decoded, bytesTest.expected);
});
});
});
// TODO(jwetzell): add error tests
const badTests = [];
describe('PSN Bytes Decoding Throws', () => {
badTests.forEach((bytesTest) => {
it(bytesTest.description, () => {
throws(() => {
bytesTest.decoder(bytesTest.bytes);
}, bytesTest.throwsMessage);
});
});
});
-193
View File
@@ -1,193 +0,0 @@
import { deepEqual, throws } from 'node:assert';
import { describe, it } from 'node:test';
import { Encoders } from '@jwetzell/posistagenet';
const goodTests = [
{
description: 'DataTrackerPosChunk',
expected: new Uint8Array([
0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
bytes: Encoders.DataTrackerPosChunk(1.0, 2.0, 3.0),
},
{
description: 'DataTrackerSpeedChunk',
expected: new Uint8Array([
1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
bytes: Encoders.DataTrackerSpeedChunk(1.0, 2.0, 3.0),
},
{
description: 'DataTrackerOriChunk',
expected: new Uint8Array([
2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
bytes: Encoders.DataTrackerOriChunk(1.0, 2.0, 3.0),
},
{
description: 'DataTrackerStatusChunk',
expected: new Uint8Array([3, 0, 4, 0, 0, 0, 128, 63]),
bytes: Encoders.DataTrackerStatusChunk(1.0),
},
{
description: 'DataTrackerAccelChunk',
expected: new Uint8Array([
4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
bytes: Encoders.DataTrackerAccelChunk(1.0, 2.0, 3.0),
},
{
description: 'DataTrackerTrgtposChunk',
expected: new Uint8Array([
5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
]),
bytes: Encoders.DataTrackerTrgtposChunk(1.0, 2.0, 3.0),
},
{
description: 'DataTrackerTimestampChunk',
expected: new Uint8Array([6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0]),
bytes: Encoders.DataTrackerTimestampChunk(1234567890n),
},
{
description: 'DataTrackerChunk',
expected: new Uint8Array([
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 1,
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0, 0,
128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0, 12,
0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128, 63,
0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
]),
bytes: Encoders.DataTrackerChunk(1, [
new Uint8Array([0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
new Uint8Array([1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
new Uint8Array([2, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
new Uint8Array([3, 0, 4, 0, 0, 0, 128, 63]),
new Uint8Array([4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
new Uint8Array([5, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64]),
new Uint8Array([6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0]),
]),
},
{
description: 'DataTrackerListChunk',
expected: new Uint8Array([
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128,
63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0,
0, 0,
]),
bytes: Encoders.DataTrackerListChunk([
new Uint8Array([
1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64,
1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128, 63, 4, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0, 0, 128,
63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0, 0, 0,
]),
]),
},
{
description: 'DataPacketChunk',
expected: new Uint8Array([
85, 103, 124, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0, 128,
63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0, 12, 0, 0,
0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2, 150, 73, 0, 0,
0, 0,
]),
bytes: Encoders.DataPacketChunk(
new Uint8Array([0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123]),
new Uint8Array([
1, 0, 104, 128, 1, 0, 100, 128, 0, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64,
0, 0, 64, 64, 1, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 2,
0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 3, 0, 4, 0, 0, 0,
128, 63, 4, 0, 12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 5, 0,
12, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 6, 0, 8, 0, 210, 2,
150, 73, 0, 0, 0, 0,
])
),
},
{
description: 'InfoTrackerNameChunk',
expected: new Uint8Array([
0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
bytes: Encoders.InfoTrackerNameChunk('Tracker 1'),
},
{
description: 'InfoSystemNameChunk',
expected: new Uint8Array([
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
]),
bytes: Encoders.InfoSystemNameChunk('PSN Server'),
},
{
description: 'InfoTrackerChunk',
expected: new Uint8Array([
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
bytes: Encoders.InfoTrackerChunk(
1,
new Uint8Array([0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49])
),
},
{
description: 'InfoTrackerListChunk',
expected: new Uint8Array([
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114,
32, 49,
]),
bytes: Encoders.InfoTrackerListChunk([
new Uint8Array([
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
]),
},
{
description: 'PacketHeaderChunk',
expected: new Uint8Array([
0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
]),
bytes: Encoders.PacketHeaderChunk(1234567890n, 2, 3, 1, 123),
},
{
description: 'InfoPacketChunk',
expected: new Uint8Array([
86, 103, 51, 128, 0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123,
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114, 2, 0, 17, 128,
1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101, 114, 32, 49,
]),
bytes: Encoders.InfoPacketChunk(
new Uint8Array([0, 0, 12, 0, 210, 2, 150, 73, 0, 0, 0, 0, 2, 3, 1, 123]),
new Uint8Array([
1, 0, 10, 0, 80, 83, 78, 32, 83, 101, 114, 118, 101, 114,
]),
new Uint8Array([
2, 0, 17, 128, 1, 0, 13, 128, 0, 0, 9, 0, 84, 114, 97, 99, 107, 101,
114, 32, 49,
])
),
},
];
describe('PSN Message Encoding', () => {
goodTests.forEach((messageTest) => {
it(messageTest.description, () => {
deepEqual(messageTest.bytes, messageTest.expected);
});
});
});
//TODO(jwetzell): add tests that handle errors
const badTests = [];
describe('PSN Message Encoding Throws', () => {
badTests.forEach((messageTest) => {
it(messageTest.description, () => {
throws(() => {}, messageTest.throwsMessage);
});
});
});
+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"
}
}
+10 -18
View File
@@ -1,20 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "moduleResolution": "Node",
"lib": ["es2023"], "lib": ["ESNext"],
"moduleDetection": "force", "target": "ESNext",
"module": "preserve", "esModuleInterop": true,
"moduleResolution": "bundler", "isolatedModules": true,
"resolveJsonModule": true, "rootDir": "src/",
"types": ["node"], "strict": true
"strict": true, },
"noUnusedLocals": true, "include": ["src/"]
"declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
},
"include": ["src"]
} }
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "./dist/types"
}
}
-10
View File
@@ -1,10 +0,0 @@
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: 'src/index.ts',
exports: true,
format: {
esm: {},
cjs: {},
},
});