convert to typescript

This commit is contained in:
2023-09-14 22:43:25 -05:00
parent 4c19f5f7b9
commit f21bef263d
64 changed files with 1109 additions and 605 deletions
+2 -1
View File
@@ -1 +1,2 @@
node_modules node_modules
dist
+1 -1
View File
@@ -1,4 +1,4 @@
const { Encoder, Decoder, Tracker } = require('.'); const { Encoder, Tracker } = require('./dist');
const testSizes = [1, 10, 100]; const testSizes = [1, 10, 100];
+3 -6
View File
@@ -1,6 +1,6 @@
// 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('dgram'); const dgram = require('dgram');
const { Decoder } = require('..'); const { Decoder } = require('../dist');
const client = dgram.createSocket('udp4'); const client = dgram.createSocket('udp4');
const decoder = new Decoder(); const decoder = new Decoder();
@@ -23,11 +23,8 @@ setInterval(() => {
} }
Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => { Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => {
console.log( const trackerName = decoder.trackers[trackerId]?.tracker_name?.tracker_name;
`Tracker - id: ${trackerId} | name: ${ console.log(`Tracker - id: ${trackerId} | name: ${trackerName || ''}`);
decoder.trackers[trackerId]?.tracker_name ? decoder.trackers[trackerId]?.tracker_name : ''
}`
);
if (tracker.pos) { if (tracker.pos) {
console.log(`\tpos: ${tracker.pos.pos_x}, ${tracker.pos.pos_y}, ${tracker.pos.pos_z}`); console.log(`\tpos: ${tracker.pos.pos_x}, ${tracker.pos.pos_y}, ${tracker.pos.pos_z}`);
} }
+1 -1
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('dgram'); const dgram = require('dgram');
const { Encoder, Tracker, Decoder } = require('..'); const { Encoder, Tracker, Decoder } = require('../dist');
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);
-9
View File
@@ -1,9 +0,0 @@
const Decoder = require('./src/decoder.js');
const Encoder = require('./src/encoder.js');
const Tracker = require('./src/models/tracker.js');
module.exports = {
Encoder,
Decoder,
Tracker,
};
+426 -20
View File
@@ -1,18 +1,21 @@
{ {
"name": "@jwetzell/posistagenet", "name": "@jwetzell/posistagenet",
"version": "0.2.1", "version": "0.3.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@jwetzell/posistagenet", "name": "@jwetzell/posistagenet",
"version": "0.2.1", "version": "0.3.0",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/node": "^20.6.0",
"eslint": "^8.48.0", "eslint": "^8.48.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.0.0",
"prettier": "^3.0.3" "prettier": "^3.0.3",
"rimraf": "^5.0.1",
"typescript": "^5.2.2"
} }
}, },
"node_modules/@aashutoshrathi/word-wrap": { "node_modules/@aashutoshrathi/word-wrap": {
@@ -126,6 +129,50 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true "dev": true
}, },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -161,6 +208,16 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@types/json5": { "node_modules/@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -168,6 +225,12 @@
"dev": true, "dev": true,
"peer": true "peer": true
}, },
"node_modules/@types/node": {
"version": "20.6.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz",
"integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==",
"dev": true
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.10.0", "version": "8.10.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
@@ -586,12 +649,17 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true, "dev": true
"peer": true
}, },
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.22.1", "version": "1.22.1",
@@ -1195,6 +1263,41 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/flat-cache/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/flat-cache/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/flatted": { "node_modules/flatted": {
"version": "3.2.7", "version": "3.2.7",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
@@ -1210,6 +1313,22 @@
"is-callable": "^1.1.3" "is-callable": "^1.1.3"
} }
}, },
"node_modules/foreground-child": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -1281,20 +1400,22 @@
} }
}, },
"node_modules/glob": { "node_modules/glob": {
"version": "7.2.3", "version": "10.3.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.4.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"fs.realpath": "^1.0.0", "foreground-child": "^3.1.0",
"inflight": "^1.0.4", "jackspeak": "^2.0.3",
"inherits": "2", "minimatch": "^9.0.1",
"minimatch": "^3.1.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"once": "^1.3.0", "path-scurry": "^1.10.1"
"path-is-absolute": "^1.0.0" },
"bin": {
"glob": "dist/cjs/src/bin.js"
}, },
"engines": { "engines": {
"node": "*" "node": ">=16 || 14 >=14.17"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
@@ -1312,6 +1433,30 @@
"node": ">=10.13.0" "node": ">=10.13.0"
} }
}, },
"node_modules/glob/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/glob/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/globals": { "node_modules/globals": {
"version": "13.21.0", "version": "13.21.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz",
@@ -1625,6 +1770,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/is-generator-function": { "node_modules/is-generator-function": {
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
@@ -1843,6 +1997,24 @@
"reflect.getprototypeof": "^1.0.3" "reflect.getprototypeof": "^1.0.3"
} }
}, },
"node_modules/jackspeak": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.3.tgz",
"integrity": "sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg==",
"dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1982,6 +2154,15 @@
"loose-envify": "cli.js" "loose-envify": "cli.js"
} }
}, },
"node_modules/lru-cache": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
"integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
}
},
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -2004,6 +2185,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/minipass": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz",
"integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -2241,6 +2431,22 @@
"dev": true, "dev": true,
"peer": true "peer": true
}, },
"node_modules/path-scurry": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"dev": true,
"dependencies": {
"lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/prelude-ls": { "node_modules/prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -2396,15 +2602,18 @@
} }
}, },
"node_modules/rimraf": { "node_modules/rimraf": {
"version": "3.0.2", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"glob": "^7.1.3" "glob": "^10.2.5"
}, },
"bin": { "bin": {
"rimraf": "bin.js" "rimraf": "dist/cjs/src/bin.js"
},
"engines": {
"node": ">=14"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
@@ -2509,6 +2718,83 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/string-width/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/string-width/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/string.prototype.matchall": { "node_modules/string.prototype.matchall": {
"version": "4.0.9", "version": "4.0.9",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.9.tgz", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.9.tgz",
@@ -2586,6 +2872,19 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom": { "node_modules/strip-bom": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
@@ -2741,6 +3040,19 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/typescript": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/unbox-primitive": { "node_modules/unbox-primitive": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -2858,6 +3170,100 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/wrap-ansi/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/wrappy": { "node_modules/wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+13 -4
View File
@@ -1,12 +1,18 @@
{ {
"name": "@jwetzell/posistagenet", "name": "@jwetzell/posistagenet",
"version": "0.3.0", "version": "0.4.0",
"description": "", "description": "",
"main": "index.js", "main": "dist/index.js",
"scripts": { "scripts": {
"prebuild": "rimraf dist",
"build": "tsc",
"example:client": "node examples/psn_client.js", "example:client": "node examples/psn_client.js",
"example:server": "node examples/psn_server.js" "example:server": "node examples/psn_server.js",
"prepublishOnly": "npm run build"
}, },
"files": [
"dist"
],
"author": { "author": {
"name": "Joel Wetzell", "name": "Joel Wetzell",
"email": "me@jwetzell.com", "email": "me@jwetzell.com",
@@ -15,9 +21,12 @@
"repository": "https://github.com/jwetzell/psn-js", "repository": "https://github.com/jwetzell/psn-js",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/node": "^20.6.0",
"eslint": "^8.48.0", "eslint": "^8.48.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.0.0",
"prettier": "^3.0.3" "prettier": "^3.0.3",
"rimraf": "^5.0.1",
"typescript": "^5.2.2"
} }
} }
-5
View File
@@ -1,5 +0,0 @@
module.exports = {
PACKET_HEADER_SIZE: 16,
MAX_UDP_PACKET_SIZE: 1500,
CHUNK_HEADER_SIZE: 4,
};
+5
View File
@@ -0,0 +1,5 @@
export class Constants {
static readonly PACKET_HEADER_SIZE = 16;
static readonly MAX_UDP_PACKET_SIZE = 1500;
static readonly CHUNK_HEADER_SIZE = 4;
}
-109
View File
@@ -1,109 +0,0 @@
const packetDecoder = require('./decoders/packet');
class Decoder {
// TODO(jwetzell): check if these last packet headers are necessary to hold on to
lastInfoPacketHeader;
lastDataPacketHeader;
infoPacketFrames = {};
dataPacketFrames = {};
constructor() {
this.system_name = '';
this.trackers = {};
}
updateInfo(framePackets) {
framePackets.forEach((packet) => {
if (packet.system_name) {
this.system_name = packet.system_name.system_name;
}
if (packet.tracker_list?.trackers) {
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
this.trackers[trackerId] = {
...this.trackers[trackerId],
...tracker.tracker_name,
};
});
}
});
}
updateData(framePackets) {
framePackets.forEach((packet) => {
if (packet.tracker_list) {
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
this.trackers[trackerId] = {
...this.trackers[trackerId],
...tracker,
};
});
}
});
}
// TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete
decode(packetBuf) {
const packet = packetDecoder(packetBuf);
if (packet.id === 0x6756) {
const infoPacket = packet;
if (infoPacket) {
if (infoPacket.has_subchunks > 0) {
const currentInfoPacketHeader = infoPacket.packet_header;
if (!currentInfoPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet');
}
const systemSubChunk = infoPacket.system_name;
if (!systemSubChunk) {
// NOTE(jwetzell): not sure that info packets without a system subchunk are valid?
throw new Error('malformed packet');
}
if (this.infoPacketFrames[currentInfoPacketHeader.frame_id] === undefined) {
this.infoPacketFrames[currentInfoPacketHeader.frame_id] = [];
}
this.infoPacketFrames[currentInfoPacketHeader.frame_id].push(infoPacket);
if (
this.infoPacketFrames[currentInfoPacketHeader.frame_id].length ===
currentInfoPacketHeader.frame_packet_count
) {
this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.frame_id]);
delete this.infoPacketFrames[currentInfoPacketHeader.frame_id];
}
this.lastInfoPacketHeader = currentInfoPacketHeader;
}
}
} else if (packet.id === 0x6755) {
const dataPacket = packet;
if (dataPacket.has_subchunks) {
const currentDataPacketHeader = dataPacket.packet_header;
if (!currentDataPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet');
}
if (this.dataPacketFrames[currentDataPacketHeader.frame_id] === undefined) {
this.dataPacketFrames[currentDataPacketHeader.frame_id] = [];
}
this.dataPacketFrames[currentDataPacketHeader.frame_id].push(dataPacket);
if (
this.dataPacketFrames[currentDataPacketHeader.frame_id].length === currentDataPacketHeader.frame_packet_count
) {
this.updateData(this.dataPacketFrames[currentDataPacketHeader.frame_id]);
delete this.dataPacketFrames[currentDataPacketHeader.frame_id];
}
this.lastDataPacketHeader = currentDataPacketHeader;
}
}
return packet;
}
}
module.exports = Decoder;
+117
View File
@@ -0,0 +1,117 @@
import { DataPacketChunk } from './decoders/data/data-packet-chunk';
import { InfoPacketChunk } from './decoders/info/info-packet-chunk';
import { InfoTrackerChunk } from './decoders/info/info-tracker-chunk';
import packetDecoder from './decoders/packet';
import { PacketHeaderChunk } from './decoders/packet-header-chunk';
export class Decoder {
// TODO(jwetzell): check if these last packet headers are necessary to hold on to
lastInfoPacketHeader?: PacketHeaderChunk;
lastDataPacketHeader?: PacketHeaderChunk;
infoPacketFrames: { [key: number]: InfoPacketChunk[] } = {};
dataPacketFrames: { [key: number]: DataPacketChunk[] } = {};
trackers: { [key: string]: InfoTrackerChunk } = {};
system_name: string = '';
constructor() {}
updateInfo(framePackets: InfoPacketChunk[]) {
framePackets.forEach((packet) => {
if (packet.system_name) {
this.system_name = packet.system_name.system_name;
}
if (packet.tracker_list?.trackers) {
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
if (!this.trackers[trackerId]) {
this.trackers[trackerId] = {};
}
this.trackers[trackerId].tracker_name = tracker.tracker_name;
});
}
});
}
updateData(framePackets: DataPacketChunk[]) {
framePackets.forEach((packet) => {
if (packet.tracker_list) {
Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => {
this.trackers[trackerId] = {
...this.trackers[trackerId],
...tracker,
};
});
}
});
}
// TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete
decode(packetBuf: Buffer): DataPacketChunk | InfoPacketChunk | undefined {
const packet = packetDecoder(packetBuf);
if (packet === undefined) {
return packet;
}
if (packet.id === 0x6756) {
const infoPacket = packet as InfoPacketChunk;
if (infoPacket && infoPacket.has_subchunks) {
const currentInfoPacketHeader = infoPacket.packet_header;
if (!currentInfoPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet');
}
const systemSubChunk = infoPacket.system_name;
if (!systemSubChunk) {
// NOTE(jwetzell): not sure that info packets without a system subchunk are valid?
throw new Error('malformed packet');
}
if (currentInfoPacketHeader.frame_id) {
if (this.infoPacketFrames[currentInfoPacketHeader.frame_id] === undefined) {
this.infoPacketFrames[currentInfoPacketHeader.frame_id] = [];
}
this.infoPacketFrames[currentInfoPacketHeader.frame_id].push(infoPacket);
if (
this.infoPacketFrames[currentInfoPacketHeader.frame_id].length ===
currentInfoPacketHeader.frame_packet_count
) {
this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.frame_id]);
delete this.infoPacketFrames[currentInfoPacketHeader.frame_id];
}
}
this.lastInfoPacketHeader = currentInfoPacketHeader;
}
} else if (packet.id === 0x6755) {
const dataPacket = packet as DataPacketChunk;
if (dataPacket.has_subchunks) {
const currentDataPacketHeader = dataPacket.packet_header;
if (!currentDataPacketHeader) {
// NOTE(jwetzell): not sure that info packets without a header subchunk are valid?
throw new Error('malformed packet');
}
if (currentDataPacketHeader.frame_id) {
if (this.dataPacketFrames[currentDataPacketHeader.frame_id] === undefined) {
this.dataPacketFrames[currentDataPacketHeader.frame_id] = [];
}
this.dataPacketFrames[currentDataPacketHeader.frame_id].push(dataPacket);
if (
this.dataPacketFrames[currentDataPacketHeader.frame_id].length ===
currentDataPacketHeader.frame_packet_count
) {
this.updateData(this.dataPacketFrames[currentDataPacketHeader.frame_id]);
delete this.dataPacketFrames[currentDataPacketHeader.frame_id];
}
}
this.lastDataPacketHeader = currentDataPacketHeader;
}
}
return packet;
}
}
@@ -1,6 +1,13 @@
module.exports = (buffer, dataDecoder) => { export interface Chunk {
id?: number;
has_subchunks?: boolean;
data_len?: number;
chunk_data?: Buffer;
}
export default (buffer: Buffer, dataDecoder: Function): Chunk => {
let offset = 0; let offset = 0;
const chunk = {}; const chunk: Chunk = {};
chunk.id = buffer.readUInt16LE(offset); chunk.id = buffer.readUInt16LE(offset);
offset += 2; offset += 2;
-29
View File
@@ -1,29 +0,0 @@
const { CHUNK_HEADER_SIZE } = require('../../constants');
const chunk = require('../chunk');
const packetHeaderChunk = require('../packet-header-chunk');
const dataTrackerListChunk = require('./data-tracker-list-chunk');
function decodeDataPacketChunk(dataPacketChunk) {
if (dataPacketChunk.has_subchunks && dataPacketChunk.chunk_data) {
let offset = 0;
while (offset < dataPacketChunk.data_len) {
const chunkId = dataPacketChunk.chunk_data.readUInt16LE(offset);
switch (chunkId) {
case 0x0000:
dataPacketChunk.packet_header = packetHeaderChunk(dataPacketChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += dataPacketChunk.packet_header.data_len;
break;
case 0x0001:
dataPacketChunk.tracker_list = dataTrackerListChunk(dataPacketChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += dataPacketChunk.tracker_list.data_len;
break;
default:
break;
}
}
}
}
module.exports = (buffer) => chunk(buffer, decodeDataPacketChunk);
+38
View File
@@ -0,0 +1,38 @@
import { Constants } from '../../constants';
import chunk, { Chunk } from '../chunk';
import packetHeaderChunk, { PacketHeaderChunk } from '../packet-header-chunk';
import dataTrackerListChunk, { DataTrackerListChunk } from './data-tracker-list-chunk';
export interface DataPacketChunk extends Chunk {
packet_header: PacketHeaderChunk;
tracker_list: DataTrackerListChunk;
}
function decodeDataPacketChunk(dataPacketChunk: DataPacketChunk) {
if (dataPacketChunk.has_subchunks && dataPacketChunk.chunk_data && dataPacketChunk.data_len) {
let offset = 0;
while (offset < dataPacketChunk.data_len) {
const chunkId = dataPacketChunk.chunk_data.readUInt16LE(offset);
switch (chunkId) {
case 0x0000:
dataPacketChunk.packet_header = packetHeaderChunk(dataPacketChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (dataPacketChunk.packet_header?.data_len) {
offset += dataPacketChunk.packet_header.data_len;
}
break;
case 0x0001:
dataPacketChunk.tracker_list = dataTrackerListChunk(dataPacketChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (dataPacketChunk.tracker_list.data_len) {
offset += dataPacketChunk.tracker_list.data_len;
}
break;
default:
break;
}
}
}
}
export default (buffer: Buffer): DataPacketChunk => chunk(buffer, decodeDataPacketChunk) as DataPacketChunk;
-41
View File
@@ -1,41 +0,0 @@
const { CHUNK_HEADER_SIZE } = require('../../constants');
const chunk = require('../chunk');
const dataTrackerFieldChunk = require('./data-tracker-field-chunk');
function decodeTrackerChunk(trackerChunk) {
if (trackerChunk.chunk_data && trackerChunk.data_len > 0) {
let offset = 0;
while (offset < trackerChunk.data_len) {
const trackerFieldChunk = dataTrackerFieldChunk(trackerChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += trackerFieldChunk.data_len;
switch (trackerFieldChunk.id) {
case 0x0000:
trackerChunk.pos = trackerFieldChunk;
break;
case 0x0001:
trackerChunk.speed = trackerFieldChunk;
break;
case 0x0002:
trackerChunk.ori = trackerFieldChunk;
break;
case 0x0003:
trackerChunk.status = trackerFieldChunk;
break;
case 0x0004:
trackerChunk.accel = trackerFieldChunk;
break;
case 0x0005:
trackerChunk.trgtpos = trackerFieldChunk;
break;
case 0x0006:
trackerChunk.timestamp = trackerFieldChunk;
break;
default:
break;
}
}
}
}
module.exports = (buffer) => chunk(buffer, decodeTrackerChunk);
+53
View File
@@ -0,0 +1,53 @@
import { Constants } from '../../constants';
import chunk, { Chunk } from '../chunk';
import dataTrackerFieldChunk, { DataTrackerFieldChunk } from './data-tracker-field-chunk';
export interface DataTrackerChunk extends Chunk {
pos: DataTrackerFieldChunk;
speed: DataTrackerFieldChunk;
ori: DataTrackerFieldChunk;
status: DataTrackerFieldChunk;
accel: DataTrackerFieldChunk;
trgtpos: DataTrackerFieldChunk;
timestamp: DataTrackerFieldChunk;
}
function decodeTrackerChunk(trackerChunk: DataTrackerChunk) {
if (trackerChunk.chunk_data && trackerChunk.data_len) {
let offset = 0;
while (offset < trackerChunk.data_len) {
const trackerFieldChunk = dataTrackerFieldChunk(trackerChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (trackerFieldChunk.data_len) {
offset += trackerFieldChunk.data_len;
switch (trackerFieldChunk.id) {
case 0x0000:
trackerChunk.pos = trackerFieldChunk;
break;
case 0x0001:
trackerChunk.speed = trackerFieldChunk;
break;
case 0x0002:
trackerChunk.ori = trackerFieldChunk;
break;
case 0x0003:
trackerChunk.status = trackerFieldChunk;
break;
case 0x0004:
trackerChunk.accel = trackerFieldChunk;
break;
case 0x0005:
trackerChunk.trgtpos = trackerFieldChunk;
break;
case 0x0006:
trackerChunk.timestamp = trackerFieldChunk;
break;
default:
break;
}
}
}
}
}
export default (buffer: Buffer): DataTrackerChunk => chunk(buffer, decodeTrackerChunk) as DataTrackerChunk;
@@ -1,43 +0,0 @@
/* eslint-disable no-case-declarations */
const chunk = require('../chunk');
function readXYZ(trackerFieldChunk, prefix) {
if (prefix === undefined) {
prefix = '';
}
trackerFieldChunk[`${prefix}x`] = trackerFieldChunk.chunk_data.readFloatLE(0);
trackerFieldChunk[`${prefix}y`] = trackerFieldChunk.chunk_data.readFloatLE(4);
trackerFieldChunk[`${prefix}z`] = trackerFieldChunk.chunk_data.readFloatLE(8);
}
function decodeTrackerFieldChunk(trackerFieldChunk) {
if (trackerFieldChunk.id !== undefined) {
switch (trackerFieldChunk.id) {
case 0x0000:
readXYZ(trackerFieldChunk, 'pos_');
break;
case 0x0001:
readXYZ(trackerFieldChunk, 'speed_');
break;
case 0x0002:
readXYZ(trackerFieldChunk, 'ori_');
break;
case 0x0003:
trackerFieldChunk.validity = trackerFieldChunk.chunk_data.readFloatLE();
break;
case 0x0004:
readXYZ(trackerFieldChunk, 'accel_');
break;
case 0x0005:
readXYZ(trackerFieldChunk, 'trgtpos_');
break;
case 0x0006:
trackerFieldChunk.tracker_timestamp = trackerFieldChunk.chunk_data.readBigUInt64LE();
break;
default:
break;
}
}
}
module.exports = (buffer) => chunk(buffer, decodeTrackerFieldChunk);
@@ -0,0 +1,50 @@
/* eslint-disable no-case-declarations */
import chunk, { Chunk } from '../chunk';
export interface DataTrackerFieldChunk extends Chunk {
[key: string]: number | bigint | number[] | Buffer | undefined | boolean;
}
function readXYZ(trackerFieldChunk: DataTrackerFieldChunk, prefix: string = '') {
if (trackerFieldChunk.chunk_data) {
trackerFieldChunk[`${prefix}x`] = trackerFieldChunk.chunk_data.readFloatLE(0);
trackerFieldChunk[`${prefix}y`] = trackerFieldChunk.chunk_data.readFloatLE(4);
trackerFieldChunk[`${prefix}z`] = trackerFieldChunk.chunk_data.readFloatLE(8);
}
}
function decodeTrackerFieldChunk(trackerFieldChunk: DataTrackerFieldChunk) {
if (trackerFieldChunk.id !== undefined) {
switch (trackerFieldChunk.id) {
case 0x0000:
readXYZ(trackerFieldChunk, 'pos_');
break;
case 0x0001:
readXYZ(trackerFieldChunk, 'speed_');
break;
case 0x0002:
readXYZ(trackerFieldChunk, 'ori_');
break;
case 0x0003:
if (trackerFieldChunk.chunk_data) {
trackerFieldChunk.validity = trackerFieldChunk.chunk_data.readFloatLE();
}
break;
case 0x0004:
readXYZ(trackerFieldChunk, 'accel_');
break;
case 0x0005:
readXYZ(trackerFieldChunk, 'trgtpos_');
break;
case 0x0006:
if (trackerFieldChunk.chunk_data) {
trackerFieldChunk.tracker_timestamp = trackerFieldChunk.chunk_data.readBigUInt64LE();
}
break;
default:
break;
}
}
}
export default (buffer: Buffer): DataTrackerFieldChunk =>
chunk(buffer, decodeTrackerFieldChunk) as DataTrackerFieldChunk;
@@ -1,17 +0,0 @@
const { CHUNK_HEADER_SIZE } = require('../../constants');
const chunk = require('../chunk');
const dataTrackerChunk = require('./data-tracker-chunk');
function decodeDataTrackerListChunk(dataTrackerListChunk) {
dataTrackerListChunk.trackers = {};
// TODO(jwetzell): add error handling
let offset = 0;
while (offset < dataTrackerListChunk.chunk_data.length) {
const trackerChunk = dataTrackerChunk(dataTrackerListChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += trackerChunk.data_len;
dataTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
}
}
module.exports = (buffer) => chunk(buffer, decodeDataTrackerListChunk);
@@ -0,0 +1,30 @@
import { Constants } from '../../constants';
import chunk, { Chunk } from '../chunk';
import dataTrackerChunk, { DataTrackerChunk } from './data-tracker-chunk';
export interface DataTrackerListChunk extends Chunk {
trackers: {
[key: number]: DataTrackerChunk;
};
}
function decodeDataTrackerListChunk(dataTrackerListChunk: DataTrackerListChunk) {
dataTrackerListChunk.trackers = {};
// TODO(jwetzell): add error handling
let offset = 0;
if (dataTrackerListChunk.chunk_data) {
while (offset < dataTrackerListChunk.chunk_data.length) {
const trackerChunk = dataTrackerChunk(dataTrackerListChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (trackerChunk.data_len) {
offset += trackerChunk.data_len;
}
if (trackerChunk.id) {
dataTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
}
}
}
}
export default (buffer: Buffer): DataTrackerListChunk =>
chunk(buffer, decodeDataTrackerListChunk) as DataTrackerListChunk;
-35
View File
@@ -1,35 +0,0 @@
const { CHUNK_HEADER_SIZE } = require('../../constants');
const chunk = require('../chunk');
const packetHeaderChunk = require('../packet-header-chunk');
const infoSystemNameChunk = require('./info-system-name-chunk');
const infoTrackerListChunk = require('./info-tracker-list-chunk');
function decodeInfoPacketChunk(infoPacketChunk) {
if (infoPacketChunk.has_subchunks && infoPacketChunk.chunk_data) {
let offset = 0;
while (offset < infoPacketChunk.data_len) {
const chunkId = infoPacketChunk.chunk_data.readUInt16LE(offset);
switch (chunkId) {
case 0x0000:
infoPacketChunk.packet_header = packetHeaderChunk(infoPacketChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += infoPacketChunk.packet_header.data_len;
break;
case 0x0001:
infoPacketChunk.system_name = infoSystemNameChunk(infoPacketChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += infoPacketChunk.system_name.data_len;
break;
case 0x0002:
infoPacketChunk.tracker_list = infoTrackerListChunk(infoPacketChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += infoPacketChunk.tracker_list.data_len;
break;
default:
break;
}
}
}
}
module.exports = (buffer) => chunk(buffer, decodeInfoPacketChunk);
+47
View File
@@ -0,0 +1,47 @@
import { Constants } from '../../constants';
import chunk, { Chunk } from '../chunk';
import packetHeaderChunk, { PacketHeaderChunk } from '../packet-header-chunk';
import infoSystemNameChunk, { InfoSystemNameChunk } from './info-system-name-chunk';
import infoTrackerListChunk, { InfoTrackerListChunk } from './info-tracker-list-chunk';
export interface InfoPacketChunk extends Chunk {
packet_header: PacketHeaderChunk;
system_name: InfoSystemNameChunk;
tracker_list: InfoTrackerListChunk;
}
function decodeInfoPacketChunk(infoPacketChunk: InfoPacketChunk) {
if (infoPacketChunk.has_subchunks && infoPacketChunk.chunk_data && infoPacketChunk.data_len) {
let offset = 0;
while (offset < infoPacketChunk.data_len) {
const chunkId = infoPacketChunk.chunk_data.readUInt16LE(offset);
switch (chunkId) {
case 0x0000:
infoPacketChunk.packet_header = packetHeaderChunk(infoPacketChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoPacketChunk.packet_header?.data_len) {
offset += infoPacketChunk.packet_header.data_len;
}
break;
case 0x0001:
infoPacketChunk.system_name = infoSystemNameChunk(infoPacketChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoPacketChunk.system_name?.data_len) {
offset += infoPacketChunk.system_name.data_len;
}
break;
case 0x0002:
infoPacketChunk.tracker_list = infoTrackerListChunk(infoPacketChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoPacketChunk.tracker_list?.data_len) {
offset += infoPacketChunk.tracker_list.data_len;
}
break;
default:
break;
}
}
}
}
export default (buffer: Buffer): InfoPacketChunk => chunk(buffer, decodeInfoPacketChunk) as InfoPacketChunk;
@@ -1,9 +0,0 @@
const chunk = require('../chunk');
function decodeSystemNameChunk(systemNameChunk) {
if (systemNameChunk.chunk_data !== undefined && systemNameChunk.data_len !== undefined) {
systemNameChunk.system_name = systemNameChunk.chunk_data.subarray(0, systemNameChunk.data_len).toString();
}
}
module.exports = (buffer) => chunk(buffer, decodeSystemNameChunk);
@@ -0,0 +1,13 @@
import chunk, { Chunk } from '../chunk';
export interface InfoSystemNameChunk extends Chunk {
system_name: string;
}
function decodeSystemNameChunk(systemNameChunk: InfoSystemNameChunk) {
if (systemNameChunk.chunk_data !== undefined && systemNameChunk.data_len !== undefined) {
systemNameChunk.system_name = systemNameChunk.chunk_data.subarray(0, systemNameChunk.data_len).toString();
}
}
export default (buffer: Buffer): InfoSystemNameChunk => chunk(buffer, decodeSystemNameChunk) as InfoSystemNameChunk;
-24
View File
@@ -1,24 +0,0 @@
const { CHUNK_HEADER_SIZE } = require('../../constants');
const chunk = require('../chunk');
const infoTrackerNameChunk = require('./info-tracker-name-chunk');
function decodeInfoTrackerChunk(infoTrackerChunk) {
if (infoTrackerChunk.has_subchunks && infoTrackerChunk.chunk_data) {
let offset = 0;
while (offset < infoTrackerChunk.data_len) {
const chunkId = infoTrackerChunk.chunk_data.readUInt16LE(offset);
switch (chunkId) {
case 0x0000:
infoTrackerChunk.tracker_name = infoTrackerNameChunk(infoTrackerChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += infoTrackerChunk.tracker_name.data_len;
break;
default:
break;
}
}
}
}
module.exports = (buffer) => chunk(buffer, decodeInfoTrackerChunk);
+30
View File
@@ -0,0 +1,30 @@
import { Constants } from '../../constants';
import chunk, { Chunk } from '../chunk';
import infoTrackerNameChunk, { InfoTrackerNameChunk } from './info-tracker-name-chunk';
export interface InfoTrackerChunk extends Chunk {
tracker_name?: InfoTrackerNameChunk;
}
function decodeInfoTrackerChunk(infoTrackerChunk: InfoTrackerChunk) {
if (infoTrackerChunk.has_subchunks && infoTrackerChunk.chunk_data && infoTrackerChunk.data_len) {
let offset = 0;
while (offset < infoTrackerChunk.data_len) {
const chunkId = infoTrackerChunk.chunk_data.readUInt16LE(offset);
switch (chunkId) {
case 0x0000:
infoTrackerChunk.tracker_name = infoTrackerNameChunk(infoTrackerChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (infoTrackerChunk.tracker_name?.data_len) {
offset += infoTrackerChunk?.tracker_name?.data_len;
}
break;
default:
break;
}
}
}
}
export default (buffer: Buffer): InfoTrackerChunk => chunk(buffer, decodeInfoTrackerChunk);
@@ -1,17 +0,0 @@
const { CHUNK_HEADER_SIZE } = require('../../constants');
const chunk = require('../chunk');
const infoTrackerChunk = require('./info-tracker-chunk');
function decodeInfoTrackerListChunk(infoTrackerListChunk) {
infoTrackerListChunk.trackers = {};
if (infoTrackerListChunk.has_subchunks && infoTrackerListChunk.chunk_data) {
let offset = 0;
while (offset < infoTrackerListChunk.data_len) {
const trackerChunk = infoTrackerChunk(infoTrackerListChunk.chunk_data.subarray(offset));
offset += CHUNK_HEADER_SIZE;
offset += trackerChunk.data_len;
infoTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
}
}
}
module.exports = (buffer) => chunk(buffer, decodeInfoTrackerListChunk);
@@ -0,0 +1,29 @@
import { Constants } from '../../constants';
import chunk, { Chunk } from '../chunk';
import infoTrackerChunk, { InfoTrackerChunk } from './info-tracker-chunk';
export interface InfoTrackerListChunk extends Chunk {
trackers: {
[key: number]: InfoTrackerChunk;
};
}
function decodeInfoTrackerListChunk(infoTrackerListChunk: InfoTrackerListChunk) {
infoTrackerListChunk.trackers = {};
if (infoTrackerListChunk.has_subchunks && infoTrackerListChunk.chunk_data) {
let offset = 0;
if (infoTrackerListChunk.data_len) {
while (offset < infoTrackerListChunk.data_len) {
const trackerChunk = infoTrackerChunk(infoTrackerListChunk.chunk_data.subarray(offset));
offset += Constants.CHUNK_HEADER_SIZE;
if (trackerChunk.data_len) {
offset += trackerChunk.data_len;
}
if (trackerChunk.id) {
infoTrackerListChunk.trackers[trackerChunk.id] = trackerChunk;
}
}
}
}
}
export default (buffer: Buffer): InfoTrackerListChunk =>
chunk(buffer, decodeInfoTrackerListChunk) as InfoTrackerListChunk;
@@ -1,8 +0,0 @@
const chunk = require('../chunk');
function decodeTrackerNameChunk(trackerNameChunk) {
if (trackerNameChunk.chunk_data !== undefined && trackerNameChunk.data_len !== undefined) {
trackerNameChunk.tracker_name = trackerNameChunk.chunk_data.subarray(0, trackerNameChunk.data_len).toString();
}
}
module.exports = (buffer) => chunk(buffer, decodeTrackerNameChunk);
@@ -0,0 +1,11 @@
import chunk, { Chunk } from '../chunk';
export interface InfoTrackerNameChunk extends Chunk {
tracker_name: string;
}
function decodeTrackerNameChunk(trackerNameChunk: InfoTrackerNameChunk) {
if (trackerNameChunk.chunk_data !== undefined && trackerNameChunk.data_len !== undefined) {
trackerNameChunk.tracker_name = trackerNameChunk.chunk_data.subarray(0, trackerNameChunk.data_len).toString();
}
}
export default (buffer: Buffer): InfoTrackerNameChunk => chunk(buffer, decodeTrackerNameChunk) as InfoTrackerNameChunk;
-12
View File
@@ -1,12 +0,0 @@
const chunk = require('./chunk');
function decodePacketHeaderChunk(packetHeaderChunk) {
// TODO(jwetzell): remove the string conversion
packetHeaderChunk.packet_timestamp = packetHeaderChunk.chunk_data.readBigUInt64LE(0);
packetHeaderChunk.version_high = packetHeaderChunk.chunk_data.readUInt8(8);
packetHeaderChunk.version_low = packetHeaderChunk.chunk_data.readUInt8(9);
packetHeaderChunk.frame_id = packetHeaderChunk.chunk_data.readUInt8(10);
packetHeaderChunk.frame_packet_count = packetHeaderChunk.chunk_data.readUInt8(11);
}
module.exports = (buffer) => chunk(buffer, decodePacketHeaderChunk);
+21
View File
@@ -0,0 +1,21 @@
import chunk, { Chunk } from './chunk';
export interface PacketHeaderChunk extends Chunk {
packet_timestamp?: bigint;
version_high?: number;
version_low?: number;
frame_id?: number;
frame_packet_count?: number;
}
function decodePacketHeaderChunk(packetHeaderChunk: PacketHeaderChunk) {
// TODO(jwetzell): remove the string conversion
if (packetHeaderChunk.chunk_data) {
packetHeaderChunk.packet_timestamp = packetHeaderChunk.chunk_data.readBigUInt64LE(0);
packetHeaderChunk.version_high = packetHeaderChunk.chunk_data.readUInt8(8);
packetHeaderChunk.version_low = packetHeaderChunk.chunk_data.readUInt8(9);
packetHeaderChunk.frame_id = packetHeaderChunk.chunk_data.readUInt8(10);
packetHeaderChunk.frame_packet_count = packetHeaderChunk.chunk_data.readUInt8(11);
}
}
export default (buffer: Buffer): PacketHeaderChunk => chunk(buffer, decodePacketHeaderChunk);
-14
View File
@@ -1,14 +0,0 @@
const dataPacketChunk = require('./data/data-packet-chunk');
const infoPacketChunk = require('./info/info-packet-chunk');
module.exports = (buffer) => {
const chunkId = buffer.readUInt16LE();
switch (chunkId) {
case 0x6756:
return infoPacketChunk(buffer);
case 0x6755:
return dataPacketChunk(buffer);
default:
return {};
}
};
+15
View File
@@ -0,0 +1,15 @@
import infoPacketChunk, { InfoPacketChunk } from './info/info-packet-chunk';
import dataPacketChunk, { DataPacketChunk } from './data/data-packet-chunk';
export default (buffer: Buffer): InfoPacketChunk | DataPacketChunk | undefined => {
const chunkId = buffer.readUInt16LE();
switch (chunkId) {
case 0x6756:
return infoPacketChunk(buffer);
case 0x6755:
return dataPacketChunk(buffer);
default:
return undefined;
}
};
+30 -27
View File
@@ -1,34 +1,39 @@
const { MAX_UDP_PACKET_SIZE, PACKET_HEADER_SIZE, CHUNK_HEADER_SIZE } = require('./constants'); import { Tracker } from './models/tracker';
const dataPacketChunk = require('./encoders/data/data-packet-chunk');
const dataTrackerListChunk = require('./encoders/data/data-tracker-list-chunk');
const infoPacketChunk = require('./encoders/info/info-packet-chunk');
const infoSystemNameChunk = require('./encoders/info/info-system-name-chunk');
const infoTrackerListChunk = require('./encoders/info/info-tracker-list-chunk');
const packetHeaderChunk = require('./encoders/packet-header-chunk');
class Encoder { import { Constants } from './constants';
constructor(systemName, versionHigh = 2, versionLow = 3) { import dataPacketChunk from './encoders/data/data-packet-chunk';
import dataTrackerListChunk from './encoders/data/data-tracker-list-chunk';
import infoPacketChunk from './encoders/info/info-packet-chunk';
import infoSystemNameChunk from './encoders/info/info-system-name-chunk';
import infoTrackerListChunk from './encoders/info/info-tracker-list-chunk';
import packetHeaderChunk from './encoders/packet-header-chunk';
export class Encoder {
private systemName: string;
private versionHigh: number;
private versionLow: number;
dataFrameId: number = 1;
infoFrameId: number = 1;
constructor(systemName: string, versionHigh: number = 2, versionLow: number = 3) {
this.systemName = systemName; this.systemName = systemName;
this.versionHigh = versionHigh; this.versionHigh = versionHigh;
this.versionLow = versionLow; this.versionLow = versionLow;
this.dataFrameId = 1;
this.infoFrameId = 1;
} }
getInfoPackets(timestamp, trackers) { getInfoPackets(timestamp: bigint, trackers: Tracker[]) {
const systemNameChunk = infoSystemNameChunk(this.systemName); const systemNameChunk = infoSystemNameChunk(this.systemName);
const trackerChunks = trackers.map((tracker) => tracker.getInfoChunk()); const trackerChunks = trackers.map((tracker: Tracker) => tracker.getInfoChunk());
const infoPackets = []; const infoPackets: Buffer[] = [];
const trackerChunksLists = []; const trackerChunksLists: Buffer[][] = [];
let currentTrackerList = []; let currentTrackerList: Buffer[] = [];
let currentInfoPacketSize = PACKET_HEADER_SIZE + systemNameChunk.length + CHUNK_HEADER_SIZE; let currentInfoPacketSize = Constants.MAX_UDP_PACKET_SIZE + systemNameChunk.length + Constants.CHUNK_HEADER_SIZE;
trackerChunks.forEach((trackerChunk) => { trackerChunks.forEach((trackerChunk: Buffer) => {
if (currentInfoPacketSize + trackerChunk.length > MAX_UDP_PACKET_SIZE) { if (currentInfoPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
trackerChunksLists.push(currentTrackerList); trackerChunksLists.push(currentTrackerList);
currentTrackerList = []; currentTrackerList = [];
currentInfoPacketSize = 0; currentInfoPacketSize = 0;
@@ -54,17 +59,17 @@ class Encoder {
return infoPackets; return infoPackets;
} }
getDataPackets(timestamp, trackers) { getDataPackets(timestamp: bigint, trackers: Tracker[]) {
const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk()); const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk());
const dataPackets = []; const dataPackets: Buffer[] = [];
const trackerChunksLists = []; const trackerChunksLists: Buffer[][] = [];
let currentTrackerList = []; let currentTrackerList: Buffer[] = [];
let currentDataPacketSize = PACKET_HEADER_SIZE + CHUNK_HEADER_SIZE; let currentDataPacketSize = Constants.PACKET_HEADER_SIZE + Constants.CHUNK_HEADER_SIZE;
allTrackerChunks.forEach((trackerChunk) => { allTrackerChunks.forEach((trackerChunk) => {
if (currentDataPacketSize + trackerChunk.length > MAX_UDP_PACKET_SIZE) { if (currentDataPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
trackerChunksLists.push(currentTrackerList); trackerChunksLists.push(currentTrackerList);
currentTrackerList = []; currentTrackerList = [];
currentDataPacketSize = 0; currentDataPacketSize = 0;
@@ -91,5 +96,3 @@ class Encoder {
return dataPackets; return dataPackets;
} }
} }
module.exports = Encoder;
@@ -1,4 +1,4 @@
module.exports = (id, chunkData, hasSubchunks) => { export default (id: number, chunkData: Buffer, hasSubchunks: boolean): Buffer => {
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');
} }
-4
View File
@@ -1,4 +0,0 @@
const chunk = require('../chunk');
module.exports = (packetHeaderChunk, trackerListChunk) =>
chunk(0x6755, Buffer.concat([packetHeaderChunk, trackerListChunk]), true);
+3
View File
@@ -0,0 +1,3 @@
import chunk from '../chunk';
export default (packetHeaderChunk: Buffer, trackerListChunk: Buffer): Buffer =>
chunk(0x6755, Buffer.concat([packetHeaderChunk, trackerListChunk]), true);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (x, y, z) => { export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12); const buf = Buffer.alloc(12);
buf.writeFloatLE(x); buf.writeFloatLE(x);
buf.writeFloatLE(y, 4); buf.writeFloatLE(y, 4);
-3
View File
@@ -1,3 +0,0 @@
const chunk = require('../chunk');
module.exports = (trackerId, fieldChunks) => chunk(trackerId, Buffer.concat(fieldChunks), fieldChunks.length > 0);
+4
View File
@@ -0,0 +1,4 @@
import chunk from '../chunk';
export default (trackerId: number, fieldChunks: Buffer[]): Buffer =>
chunk(trackerId, Buffer.concat(fieldChunks), fieldChunks.length > 0);
@@ -1,3 +0,0 @@
const chunk = require('../chunk');
module.exports = (trackerChunks) => chunk(0x0001, Buffer.concat(trackerChunks), true);
@@ -0,0 +1,3 @@
import chunk from '../chunk';
export default (trackerChunks: Buffer[]) => chunk(0x0001, Buffer.concat(trackerChunks), true);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (x, y, z) => { export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12); const buf = Buffer.alloc(12);
buf.writeFloatLE(x); buf.writeFloatLE(x);
buf.writeFloatLE(y, 4); buf.writeFloatLE(y, 4);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (x, y, z) => { export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12); const buf = Buffer.alloc(12);
buf.writeFloatLE(x); buf.writeFloatLE(x);
buf.writeFloatLE(y, 4); buf.writeFloatLE(y, 4);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (x, y, z) => { export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12); const buf = Buffer.alloc(12);
buf.writeFloatLE(x); buf.writeFloatLE(x);
buf.writeFloatLE(y, 4); buf.writeFloatLE(y, 4);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (validity) => { export default (validity: number): Buffer => {
const buf = Buffer.alloc(4); const buf = Buffer.alloc(4);
buf.writeFloatLE(validity); buf.writeFloatLE(validity);
return chunk(0x0003, buf, false); return chunk(0x0003, buf, false);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (timestamp) => { export default (timestamp: bigint): Buffer => {
const buf = Buffer.alloc(8); const buf = Buffer.alloc(8);
buf.writeBigUInt64LE(BigInt(timestamp)); buf.writeBigUInt64LE(BigInt(timestamp));
return chunk(0x0006, buf, false); return chunk(0x0006, buf, false);
@@ -1,6 +1,6 @@
const chunk = require('../chunk'); import chunk from '../chunk';
module.exports = (x, y, z) => { export default (x: number, y: number, z: number): Buffer => {
const buf = Buffer.alloc(12); const buf = Buffer.alloc(12);
buf.writeFloatLE(x); buf.writeFloatLE(x);
buf.writeFloatLE(y, 4); buf.writeFloatLE(y, 4);
-4
View File
@@ -1,4 +0,0 @@
const chunk = require('../chunk');
module.exports = (packetHeaderChunk, systemNameChunk, trackerListChunk) =>
chunk(0x6756, Buffer.concat([packetHeaderChunk, systemNameChunk, trackerListChunk]), true);
+4
View File
@@ -0,0 +1,4 @@
import chunk from '../chunk';
export default (packetHeaderChunk: Buffer, systemNameChunk: Buffer, trackerListChunk: Buffer): Buffer =>
chunk(0x6756, Buffer.concat([packetHeaderChunk, systemNameChunk, trackerListChunk]), true);
@@ -1,3 +0,0 @@
const chunk = require('../chunk');
module.exports = (systemName) => chunk(0x0001, Buffer.from(systemName), false);
@@ -0,0 +1,3 @@
import chunk from '../chunk';
export default (systemName: string): Buffer => chunk(0x0001, Buffer.from(systemName), false);
-3
View File
@@ -1,3 +0,0 @@
const chunk = require('../chunk');
module.exports = (trackerId, trackerNameChunk) => chunk(trackerId, trackerNameChunk, true);
+3
View File
@@ -0,0 +1,3 @@
import chunk from '../chunk';
export default (trackerId: number, trackerNameChunk: Buffer): Buffer => chunk(trackerId, trackerNameChunk, true);
@@ -1,3 +0,0 @@
const chunk = require('../chunk');
module.exports = (trackerChunks) => chunk(0x0002, Buffer.concat(trackerChunks), true);
@@ -0,0 +1,3 @@
import chunk from '../chunk';
export default (trackerChunks: Buffer[]): Buffer => chunk(0x0002, Buffer.concat(trackerChunks), true);
@@ -1,3 +0,0 @@
const chunk = require('../chunk');
module.exports = (trackerName) => chunk(0x0000, Buffer.from(trackerName), false);
@@ -0,0 +1,3 @@
import chunk from '../chunk';
export default (trackerName: string) => chunk(0x0000, Buffer.from(trackerName), false);
@@ -1,6 +1,12 @@
const chunk = require('./chunk'); import chunk from './chunk';
module.exports = (timestamp, versionHigh, versionLow, frameId, framePacketCount) => { export default (
timestamp: bigint,
versionHigh: number,
versionLow: number,
frameId: number,
framePacketCount: number
): Buffer => {
if (frameId > 255) { if (frameId > 255) {
throw new Error('frame id must be >= 0 and <= 255'); throw new Error('frame id must be >= 0 and <= 255');
} }
+3
View File
@@ -0,0 +1,3 @@
export { Decoder } from './decoder';
export { Encoder } from './encoder';
export { Tracker } from './models/tracker';
-128
View File
@@ -1,128 +0,0 @@
const dataTrackerAccelChunk = require('../encoders/data/data-tracker-accel-chunk');
const dataTrackerChunk = require('../encoders/data/data-tracker-chunk');
const dataTrackerOriChunk = require('../encoders/data/data-tracker-ori-chunk');
const dataTrackerPosChunk = require('../encoders/data/data-tracker-pos-chunk');
const dataTrackerSpeedChunk = require('../encoders/data/data-tracker-speed-chunk');
const dataTrackerStatusChunk = require('../encoders/data/data-tracker-status-chunk');
const dataTrackerTimestampChunk = require('../encoders/data/data-tracker-timestamp-chunk');
const dataTrackerTrgtposChunk = require('../encoders/data/data-tracker-trgtpos-chunk');
const infoTrackerChunk = require('../encoders/info/info-tracker-chunk');
const infoTrackerNameChunk = require('../encoders/info/info-tracker-name-chunk');
class Tracker {
/**
* @constructor
* @param {number} id - tracker id
* @param {string} name - tracker name
*/
constructor(id, name) {
this.id = id;
this.name = name;
this.pos = undefined;
this.speed = undefined;
this.ori = undefined;
this.validity = undefined;
this.accel = undefined;
this.trgtpos = undefined;
this.timestamp = undefined;
}
/**
* @param {float} x
* @param {float} y
* @param {float} z
*/
setPos(x, y, z) {
this.pos = [x, y, z];
}
/**
* @param {float} x
* @param {float} y
* @param {float} z
*/
setSpeed(x, y, z) {
this.speed = [x, y, z];
}
/**
* @param {float} x
* @param {float} y
* @param {float} z
*/
setOri(x, y, z) {
this.ori = [x, y, z];
}
/**
* @param {float} validity
*/
setStatus(validity) {
this.validity = validity;
}
/**
* @param {float} x
* @param {float} y
* @param {float} z
*/
setAccel(x, y, z) {
this.accel = [x, y, z];
}
/**
* @param {float} x
* @param {float} y
* @param {float} z
*/
setTrgtPos(x, y, z) {
this.trgtpos = [x, y, z];
}
/**
* @param {BigInt} timestamp
*/
setTimestamp(timestamp) {
this.timestamp = timestamp;
}
getDataChunk() {
const fieldChunks = [];
if (this.pos) {
fieldChunks.push(dataTrackerPosChunk(...this.pos));
}
if (this.speed) {
fieldChunks.push(dataTrackerSpeedChunk(...this.speed));
}
if (this.ori) {
fieldChunks.push(dataTrackerOriChunk(...this.ori));
}
if (this.validity) {
fieldChunks.push(dataTrackerStatusChunk(this.validity));
}
if (this.accel) {
fieldChunks.push(dataTrackerAccelChunk(...this.accel));
}
if (this.trgtpos) {
fieldChunks.push(dataTrackerTrgtposChunk(...this.trgtpos));
}
if (this.timestamp) {
fieldChunks.push(dataTrackerTimestampChunk(this.timestamp));
}
return dataTrackerChunk(this.id, fieldChunks);
}
getInfoChunk() {
return infoTrackerChunk(this.id, infoTrackerNameChunk(this.name));
}
}
module.exports = Tracker;
+100
View File
@@ -0,0 +1,100 @@
import dataTrackerAccelChunk from '../encoders/data/data-tracker-accel-chunk';
import dataTrackerChunk from '../encoders/data/data-tracker-chunk';
import dataTrackerOriChunk from '../encoders/data/data-tracker-ori-chunk';
import dataTrackerPosChunk from '../encoders/data/data-tracker-pos-chunk';
import dataTrackerSpeedChunk from '../encoders/data/data-tracker-speed-chunk';
import dataTrackerStatusChunk from '../encoders/data/data-tracker-status-chunk';
import dataTrackerTimestampChunk from '../encoders/data/data-tracker-timestamp-chunk';
import dataTrackerTrgtposChunk from '../encoders/data/data-tracker-trgtpos-chunk';
import infoTrackerChunk from '../encoders/info/info-tracker-chunk';
import infoTrackerNameChunk from '../encoders/info/info-tracker-name-chunk';
export class Tracker {
id: number;
name: string;
pos?: [number, number, number];
speed?: [number, number, number];
ori?: [number, number, number];
validity?: number;
accel?: [number, number, number];
trgtpos?: [number, number, number];
timestamp?: bigint;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
this.pos = undefined;
this.speed = undefined;
this.ori = undefined;
this.validity = undefined;
this.accel = undefined;
this.trgtpos = undefined;
this.timestamp = undefined;
}
setPos(x: number, y: number, z: number) {
this.pos = [x, y, z];
}
setSpeed(x: number, y: number, z: number) {
this.speed = [x, y, z];
}
setOri(x: number, y: number, z: number) {
this.ori = [x, y, z];
}
setStatus(validity: number) {
this.validity = validity;
}
setAccel(x: number, y: number, z: number) {
this.accel = [x, y, z];
}
setTrgtPos(x: number, y: number, z: number) {
this.trgtpos = [x, y, z];
}
setTimestamp(timestamp: bigint) {
this.timestamp = timestamp;
}
getDataChunk() {
const fieldChunks: Buffer[] = [];
if (this.pos) {
fieldChunks.push(dataTrackerPosChunk(...this.pos));
}
if (this.speed) {
fieldChunks.push(dataTrackerSpeedChunk(...this.speed));
}
if (this.ori) {
fieldChunks.push(dataTrackerOriChunk(...this.ori));
}
if (this.validity) {
fieldChunks.push(dataTrackerStatusChunk(this.validity));
}
if (this.accel) {
fieldChunks.push(dataTrackerAccelChunk(...this.accel));
}
if (this.trgtpos) {
fieldChunks.push(dataTrackerTrgtposChunk(...this.trgtpos));
}
if (this.timestamp) {
fieldChunks.push(dataTrackerTimestampChunk(this.timestamp));
}
return dataTrackerChunk(this.id, fieldChunks);
}
getInfoChunk() {
return infoTrackerChunk(this.id, infoTrackerNameChunk(this.name));
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"esModuleInterop": true,
"module": "commonjs",
"target": "es2016",
"declaration": true,
"moduleResolution": "node",
"rootDir": "./src",
"strict": true,
"outDir": "dist"
},
"exclude": ["node_modules", "dist", "examples"]
}