diff --git a/examples/decode.js b/examples/decode.js index 6c5ae27..efca077 100644 --- a/examples/decode.js +++ b/examples/decode.js @@ -17,7 +17,7 @@ decoder.decode(infoPacketBuffer); decoder.decode(dataPacketBuffer); // the system_name from info packets if available -console.log(decoder.system_name); +console.log(decoder.systemName); // map of trackers populated with any data that has been received // this merges both info and data packet properties into one diff --git a/examples/psn_client.js b/examples/psn_client.js index f4658eb..8c13fcd 100644 --- a/examples/psn_client.js +++ b/examples/psn_client.js @@ -23,18 +23,18 @@ setInterval(() => { } Object.entries(decoder.trackers).forEach(([trackerId, tracker]) => { - const trackerName = decoder.trackers[trackerId]?.tracker_name?.tracker_name; + const trackerName = decoder.trackers[trackerId]?.name; console.log(`Tracker - id: ${trackerId} | name: ${trackerName || ''}`); if (tracker.pos) { - console.log(`\tpos: ${tracker.pos.pos_x}, ${tracker.pos.pos_y}, ${tracker.pos.pos_z}`); + console.log(`\tpos: ${tracker.pos.x}, ${tracker.pos.x}, ${tracker.pos.x}`); } if (tracker.speed) { - console.log(`\tspeed: ${tracker.speed.speed_x}, ${tracker.speed.speed_y}, ${tracker.speed.speed_z}`); + console.log(`\tspeed: ${tracker.speed.x}, ${tracker.speed.y}, ${tracker.speed.z}`); } if (tracker.ori) { - console.log(`\tori: ${tracker.ori.ori_x}, ${tracker.ori.ori_y}, ${tracker.ori.ori_z}`); + console.log(`\tori: ${tracker.ori.x}, ${tracker.ori.y}, ${tracker.ori.z}`); } if (tracker.status) { @@ -42,17 +42,15 @@ setInterval(() => { } if (tracker.accel) { - console.log(`\taccel: ${tracker.accel.accel_x}, ${tracker.accel.accel_y}, ${tracker.accel.accel_z}`); + console.log(`\taccel: ${tracker.accel.x}, ${tracker.accel.y}, ${tracker.accel.z}`); } if (tracker.trgtpos) { - console.log( - `\ttrgtpos: ${tracker.trgtpos.trgtpos_x}, ${tracker.trgtpos.trgtpos_y}, ${tracker.trgtpos.trgtpos_z}` - ); + console.log(`\ttrgtpos: ${tracker.trgtpos.x}, ${tracker.trgtpos.y}, ${tracker.trgtpos.z}`); } if (tracker.timestamp) { - console.log(`\ttimestamp: ${tracker.timestamp.tracker_timestamp}`); + console.log(`\ttimestamp: ${tracker.timestamp}`); } }); }, 1000); diff --git a/examples/psn_server.js b/examples/psn_server.js index ce0b73b..a07c682 100644 --- a/examples/psn_server.js +++ b/examples/psn_server.js @@ -1,10 +1,9 @@ // recreation of psn_server.cpp example from https://github.com/vyv/psn-cpp const dgram = require('dgram'); -const { Encoder, Tracker, Decoder } = require('../dist/cjs'); +const { Encoder, Tracker } = require('../dist/cjs'); const client = dgram.createSocket('udp4'); const encoder = new Encoder('Test PSN Server', 2, 0); -const decoder = new Decoder(); const trackers = []; @@ -40,25 +39,18 @@ setInterval(() => { trackers[index].setTimestamp(timestamp); }); + console.log(`Sending Data Packets`); const dataPackets = encoder.getDataPackets(timestamp, trackers); - dataPackets.forEach((packet, index) => { - const decodedPacket = decoder.decode(packet); - console.log( - `Sending PSN_DATA_PACKET : Frame Id = ${decodedPacket.packet_header.frame_id} , Packet Count = ${index + 1}` - ); + dataPackets.forEach((packet) => { client.send(packet, 56565, '236.10.10.10'); }); timestamp += 1; }, 5); setInterval(() => { + console.log(`Sending Info Packets`); const infoPackets = encoder.getInfoPackets(timestamp, trackers); - infoPackets.forEach((packet, index) => { - const decodedPacket = decoder.decode(packet); - console.log( - `Sending PSN_INFO_PACKET : Frame Id = ${decodedPacket.packet_header.frame_id} , Packet Count = ${index + 1}` - ); - + infoPackets.forEach((packet) => { client.send(packet, 56565, '236.10.10.10'); }); }, 500); diff --git a/src/decoder.ts b/src/decoder.ts index 86f98d5..2b993e0 100644 --- a/src/decoder.ts +++ b/src/decoder.ts @@ -1,28 +1,32 @@ import { Decoders } from '.'; -import { DataPacketChunk, InfoPacketChunk, InfoTrackerChunk } from './models'; +import { DataPacketChunk, InfoPacketChunk, Tracker, TrackerFromData, TrackerFromInfo } from './models'; export class Decoder { infoPacketFrames: { [key: number]: InfoPacketChunk[] } = {}; dataPacketFrames: { [key: number]: DataPacketChunk[] } = {}; - trackers: { [key: string]: InfoTrackerChunk } = {}; + trackers: { [key: string]: Tracker } = {}; - system_name: string = ''; + systemName: string = ''; constructor() {} updateInfo(framePackets: InfoPacketChunk[]) { framePackets.forEach((packet) => { - if (packet.system_name) { - this.system_name = packet.system_name.system_name; + if (packet.data.systemName?.data) { + this.systemName = packet.data.systemName?.data.systemName; } - if (packet.tracker_list?.trackers) { - Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => { - if (!this.trackers[trackerId]) { - this.trackers[trackerId] = {}; + if (packet.data.trackerList?.data) { + packet.data.trackerList.data.trackers.forEach((infoTrackerChunk) => { + if (!this.trackers[infoTrackerChunk.chunk.header.id]) { + const tracker = TrackerFromInfo(infoTrackerChunk); + if (tracker) { + this.trackers[infoTrackerChunk.chunk.header.id] = tracker; + } } - this.trackers[trackerId].tracker_name = tracker.tracker_name; + const tracker = this.trackers[infoTrackerChunk.chunk.header.id]; + tracker.updateInfo(infoTrackerChunk); }); } }); @@ -30,94 +34,80 @@ export class Decoder { updateData(framePackets: DataPacketChunk[]) { framePackets.forEach((packet) => { - if (packet.tracker_list) { - Object.entries(packet.tracker_list.trackers).forEach(([trackerId, tracker]) => { - this.trackers[trackerId] = { - ...this.trackers[trackerId], - ...tracker, - }; + if (packet.data.trackerList) { + packet.data.trackerList?.data.trackers.forEach((dataTrackerChunk) => { + if (!this.trackers[dataTrackerChunk.chunk.header.id]) { + const tracker = TrackerFromData(dataTrackerChunk); + if (tracker) { + this.trackers[dataTrackerChunk.chunk.header.id] = tracker; + } + } + const tracker = this.trackers[dataTrackerChunk.chunk.header.id]; + tracker.updateData(dataTrackerChunk); }); } }); } // TODO(jwetzell): add invalid frame id decoding. Scenario where a frame id is reused before one is complete - decode(packetBuf: Uint8Array): DataPacketChunk | InfoPacketChunk | undefined { - const packet = Decoders.Packet(packetBuf); + decode(packetBuf: Uint8Array) { + const packet = Decoders.Chunk(packetBuf); if (packet === undefined) { return packet; } - if (packet.id === 0x6756) { - const infoPacket = packet as InfoPacketChunk; - if (infoPacket && infoPacket.has_subchunks) { - const currentInfoPacketHeader = infoPacket.packet_header; + if (packet.header.id === 0x6756) { + const infoPacket = Decoders.InfoPacketChunk(packetBuf); + if (infoPacket && infoPacket.chunk.header.hasSubchunks) { + const currentInfoPacketHeader = infoPacket.data.packetHeader; if (!currentInfoPacketHeader) { // NOTE(jwetzell): not sure that info packets without a header subchunk are valid? throw new Error('malformed packet'); } - const systemSubChunk = infoPacket.system_name; + const systemSubChunk = infoPacket.data.systemName; if (!systemSubChunk) { // NOTE(jwetzell): not sure that info packets without a system subchunk are valid? throw new Error('malformed packet'); } - if (currentInfoPacketHeader.frame_id) { - if (this.infoPacketFrames[currentInfoPacketHeader.frame_id] === undefined) { - this.infoPacketFrames[currentInfoPacketHeader.frame_id] = []; + if (currentInfoPacketHeader.data.frameId) { + if (this.infoPacketFrames[currentInfoPacketHeader.data.frameId] === undefined) { + this.infoPacketFrames[currentInfoPacketHeader.data.frameId] = []; } - this.infoPacketFrames[currentInfoPacketHeader.frame_id].push(infoPacket); + this.infoPacketFrames[currentInfoPacketHeader.data.frameId].push(infoPacket); if ( - this.infoPacketFrames[currentInfoPacketHeader.frame_id].length === - currentInfoPacketHeader.frame_packet_count + this.infoPacketFrames[currentInfoPacketHeader.data.frameId].length === + currentInfoPacketHeader.data.framePacketCount ) { - this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.frame_id]); - delete this.infoPacketFrames[currentInfoPacketHeader.frame_id]; + this.updateInfo(this.infoPacketFrames[currentInfoPacketHeader.data.frameId]); + delete this.infoPacketFrames[currentInfoPacketHeader.data.frameId]; } } } - } else if (packet.id === 0x6755) { - const dataPacket = packet as DataPacketChunk; - if (dataPacket.has_subchunks) { - const currentDataPacketHeader = dataPacket.packet_header; + } else if (packet.header.id === 0x6755) { + const dataPacket = Decoders.DataPacketChunk(packetBuf); + if (dataPacket.chunk.header.hasSubchunks) { + const currentDataPacketHeader = dataPacket.data.packetHeader; if (!currentDataPacketHeader) { // NOTE(jwetzell): not sure that info packets without a header subchunk are valid? throw new Error('malformed packet'); } - if (currentDataPacketHeader.frame_id) { - if (this.dataPacketFrames[currentDataPacketHeader.frame_id] === undefined) { - this.dataPacketFrames[currentDataPacketHeader.frame_id] = []; + if (currentDataPacketHeader.data.frameId) { + if (this.dataPacketFrames[currentDataPacketHeader.data.frameId] === undefined) { + this.dataPacketFrames[currentDataPacketHeader.data.frameId] = []; } - this.dataPacketFrames[currentDataPacketHeader.frame_id].push(dataPacket); + this.dataPacketFrames[currentDataPacketHeader.data.frameId].push(dataPacket); if ( - this.dataPacketFrames[currentDataPacketHeader.frame_id].length === - currentDataPacketHeader.frame_packet_count + this.dataPacketFrames[currentDataPacketHeader.data.frameId].length === + currentDataPacketHeader.data.framePacketCount ) { - this.updateData(this.dataPacketFrames[currentDataPacketHeader.frame_id]); - delete this.dataPacketFrames[currentDataPacketHeader.frame_id]; + this.updateData(this.dataPacketFrames[currentDataPacketHeader.data.frameId]); + delete this.dataPacketFrames[currentDataPacketHeader.data.frameId]; } } } } - return packet; - } - - // NOTE(jwetzell): gets merged set of tracker field keys minus the guaranteed properties - getTrackerFields(): Set { - const keys = new Set( - Object.values(this.trackers) - .map((tracker) => Object.keys(tracker)) - .flat(1) - ); - - // NOTE(jwetzell): remove fields that definitely exist - keys.delete('id'); - keys.delete('has_subchunks'); - keys.delete('data_len'); - keys.delete('chunk_data'); - - return keys; } } diff --git a/src/decoders/chunk.ts b/src/decoders/chunk.ts index 2d88811..52c1693 100644 --- a/src/decoders/chunk.ts +++ b/src/decoders/chunk.ts @@ -1,19 +1,29 @@ import { Chunk } from '../models/chunk'; -export default (buffer: Uint8Array, dataDecoder: Function): Chunk => { +export default (buffer: Uint8Array): Chunk => { let offset = 0; const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); - const chunk: Chunk = {}; - chunk.id = view.getUint16(offset, true); + const id = view.getUint16(offset, true); offset += 2; // NOTE(jwetzell): this data is split up as 1 bit for has_subchunks and 15 bits for the data_len const combinedLengthAndFlag = view.getUint16(offset, true); - chunk.has_subchunks = combinedLengthAndFlag > 32768; - chunk.data_len = chunk.has_subchunks ? combinedLengthAndFlag - 32768 : combinedLengthAndFlag; + const hasSubchunks = combinedLengthAndFlag > 32768; + const dataLen = hasSubchunks ? combinedLengthAndFlag - 32768 : combinedLengthAndFlag; offset += 2; - chunk.chunk_data = buffer.slice(offset, offset + chunk.data_len); - dataDecoder(chunk); + const header = { + id, + dataLen, + hasSubchunks, + }; + + const chunkData = buffer.subarray(offset, offset + header.dataLen); + + const chunk = { + chunkData, + header, + }; + return chunk; }; diff --git a/src/decoders/data/data-packet-chunk.ts b/src/decoders/data/data-packet-chunk.ts index 5524491..0519f32 100644 --- a/src/decoders/data/data-packet-chunk.ts +++ b/src/decoders/data/data-packet-chunk.ts @@ -1,30 +1,30 @@ import { Decoders } from '..'; import { Constants } from '../../constants'; -import { DataPacketChunk } from '../../models/data/data-packet-chunk'; +import { DataPacketChunk, DataPacketChunkData } from '../../models/data/data-packet-chunk'; -function decodeDataPacketChunk(dataPacketChunk: DataPacketChunk) { - if (dataPacketChunk.has_subchunks && dataPacketChunk.chunk_data && dataPacketChunk.data_len) { +export default (buffer: Uint8Array): DataPacketChunk => { + const chunk = Decoders.Chunk(buffer); + + const data: DataPacketChunkData = {}; + + if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) { let offset = 0; - while (offset < dataPacketChunk.data_len) { - const view = new DataView( - dataPacketChunk.chunk_data.buffer, - dataPacketChunk.chunk_data.byteOffset, - dataPacketChunk.chunk_data.byteLength - ); + while (offset < chunk.header.dataLen) { + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); const chunkId = view.getUint16(offset, true); switch (chunkId) { case 0x0000: - dataPacketChunk.packet_header = Decoders.PacketHeaderChunk(dataPacketChunk.chunk_data.slice(offset)); + data.packetHeader = Decoders.PacketHeaderChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (dataPacketChunk.packet_header?.data_len) { - offset += dataPacketChunk.packet_header.data_len; + if (data.packetHeader.chunk.header.dataLen) { + offset += data.packetHeader.chunk.header.dataLen; } break; case 0x0001: - dataPacketChunk.tracker_list = Decoders.DataTrackerListChunk(dataPacketChunk.chunk_data.slice(offset)); + data.trackerList = Decoders.DataTrackerListChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (dataPacketChunk.tracker_list.data_len) { - offset += dataPacketChunk.tracker_list.data_len; + if (data.trackerList.chunk.header.dataLen) { + offset += data.trackerList.chunk.header.dataLen; } break; default: @@ -32,7 +32,9 @@ function decodeDataPacketChunk(dataPacketChunk: DataPacketChunk) { } } } -} -export default (buffer: Uint8Array): DataPacketChunk => - Decoders.Chunk(buffer, decodeDataPacketChunk) as DataPacketChunk; + return { + chunk, + data, + }; +}; diff --git a/src/decoders/data/data-tracker-chunk.ts b/src/decoders/data/data-tracker-chunk.ts index 121bc4f..c1101d3 100644 --- a/src/decoders/data/data-tracker-chunk.ts +++ b/src/decoders/data/data-tracker-chunk.ts @@ -1,43 +1,46 @@ import { Decoders } from '..'; import { Constants } from '../../constants'; -import { DataTrackerChunk } from '../../models/data/data-tracker-chunk'; +import { DataTrackerChunk, DataTrackerChunkData } from '../../models/data/data-tracker-chunk'; -function decodeTrackerChunk(trackerChunk: DataTrackerChunk) { - if (trackerChunk.chunk_data && trackerChunk.data_len) { +export default (buffer: Uint8Array): DataTrackerChunk => { + const chunk = Decoders.Chunk(buffer); + const data: DataTrackerChunkData = {}; + if (chunk.chunkData && chunk.header.dataLen) { let offset = 0; - while (offset < trackerChunk.data_len) { - const trackerFieldChunk = Decoders.DataTrackerFieldChunk(trackerChunk.chunk_data.slice(offset)); - offset += Constants.CHUNK_HEADER_SIZE; - if (trackerFieldChunk.data_len) { - offset += trackerFieldChunk.data_len; - switch (trackerFieldChunk.id) { - case 0x0000: - trackerChunk.pos = trackerFieldChunk; - break; - case 0x0001: - trackerChunk.speed = trackerFieldChunk; - break; - case 0x0002: - trackerChunk.ori = trackerFieldChunk; - break; - case 0x0003: - trackerChunk.status = trackerFieldChunk; - break; - case 0x0004: - trackerChunk.accel = trackerFieldChunk; - break; - case 0x0005: - trackerChunk.trgtpos = trackerFieldChunk; - break; - case 0x0006: - trackerChunk.timestamp = trackerFieldChunk; - break; - default: - break; - } + while (offset < chunk.header.dataLen) { + const trackerFieldChunk = Decoders.Chunk(chunk.chunkData.subarray(offset)); + switch (trackerFieldChunk.header.id) { + case 0x0000: + data.pos = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset)); + break; + case 0x0001: + data.speed = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset)); + break; + case 0x0002: + data.ori = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset)); + break; + case 0x0003: + data.status = Decoders.DataTrackerStatusChunk(chunk.chunkData.subarray(offset)); + break; + case 0x0004: + data.accel = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset)); + break; + case 0x0005: + data.trgtpos = Decoders.DataTrackerXYZChunk(chunk.chunkData.subarray(offset)); + break; + case 0x0006: + data.timestamp = Decoders.DataTrackerTimestampChunk(chunk.chunkData.subarray(offset)); + break; + default: + break; } + offset += Constants.CHUNK_HEADER_SIZE; + offset += trackerFieldChunk.header.dataLen; } } -} -export default (buffer: Uint8Array): DataTrackerChunk => Decoders.Chunk(buffer, decodeTrackerChunk) as DataTrackerChunk; + return { + chunk, + data, + }; +}; diff --git a/src/decoders/data/data-tracker-field-chunk.ts b/src/decoders/data/data-tracker-field-chunk.ts deleted file mode 100644 index cd089a4..0000000 --- a/src/decoders/data/data-tracker-field-chunk.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* eslint-disable no-case-declarations */ - -import { Decoders } from '..'; -import { DataTrackerFieldChunk } from '../../models/data/data-tracker-field-chunk'; - -function readXYZ(trackerFieldChunk: DataTrackerFieldChunk, prefix: string = '') { - if (trackerFieldChunk.chunk_data) { - const view = new DataView( - trackerFieldChunk.chunk_data.buffer, - trackerFieldChunk.chunk_data.byteOffset, - trackerFieldChunk.chunk_data.byteLength - ); - trackerFieldChunk[`${prefix}x`] = view.getFloat32(0, true); - trackerFieldChunk[`${prefix}y`] = view.getFloat32(4, true); - trackerFieldChunk[`${prefix}z`] = view.getFloat32(8, true); - } -} -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) { - const view = new DataView( - trackerFieldChunk.chunk_data.buffer, - trackerFieldChunk.chunk_data.byteOffset, - trackerFieldChunk.chunk_data.byteLength - ); - trackerFieldChunk.validity = view.getFloat32(0, true); - } - break; - case 0x0004: - readXYZ(trackerFieldChunk, 'accel_'); - break; - case 0x0005: - readXYZ(trackerFieldChunk, 'trgtpos_'); - break; - case 0x0006: - if (trackerFieldChunk.chunk_data) { - const view = new DataView( - trackerFieldChunk.chunk_data.buffer, - trackerFieldChunk.chunk_data.byteOffset, - trackerFieldChunk.chunk_data.byteLength - ); - trackerFieldChunk.tracker_timestamp = view.getBigUint64(0, true); - } - break; - default: - break; - } - } -} - -export default (buffer: Uint8Array): DataTrackerFieldChunk => - Decoders.Chunk(buffer, decodeTrackerFieldChunk) as DataTrackerFieldChunk; diff --git a/src/decoders/data/data-tracker-list-chunk.ts b/src/decoders/data/data-tracker-list-chunk.ts index 9332d1d..7398bc6 100644 --- a/src/decoders/data/data-tracker-list-chunk.ts +++ b/src/decoders/data/data-tracker-list-chunk.ts @@ -1,24 +1,33 @@ import { Decoders } from '..'; import { Constants } from '../../constants'; -import { DataTrackerListChunk } from '../../models/data/data-tracker-list-chunk'; +import { DataTrackerChunk } from '../../models'; +import { DataTrackerListChunk, DataTrackerListChunkData } from '../../models/data/data-tracker-list-chunk'; -function decodeDataTrackerListChunk(dataTrackerListChunk: DataTrackerListChunk) { - dataTrackerListChunk.trackers = {}; +export default (buffer: Uint8Array): DataTrackerListChunk => { + const chunk = Decoders.Chunk(buffer); + const trackers: DataTrackerChunk[] = []; // TODO(jwetzell): add error handling - let offset = 0; - if (dataTrackerListChunk.chunk_data) { - while (offset < dataTrackerListChunk.chunk_data.length) { - const trackerChunk = Decoders.DataTrackerChunk(dataTrackerListChunk.chunk_data.slice(offset)); + if (chunk.chunkData) { + let offset = 0; + while (offset < chunk.chunkData.length) { + const trackerChunk = Decoders.DataTrackerChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (trackerChunk.data_len) { - offset += trackerChunk.data_len; + if (trackerChunk.chunk.header.dataLen) { + offset += trackerChunk.chunk.header.dataLen; } - if (trackerChunk.id !== undefined) { - dataTrackerListChunk.trackers[trackerChunk.id] = trackerChunk; + if (trackerChunk.chunk.header.id !== undefined) { + trackers.push(trackerChunk); } } } -} -export default (buffer: Uint8Array): DataTrackerListChunk => - Decoders.Chunk(buffer, decodeDataTrackerListChunk) as DataTrackerListChunk; + + const data: DataTrackerListChunkData = { + trackers, + }; + + return { + chunk, + data, + }; +}; diff --git a/src/decoders/data/data-tracker-status-chunk.ts b/src/decoders/data/data-tracker-status-chunk.ts new file mode 100644 index 0000000..683e67e --- /dev/null +++ b/src/decoders/data/data-tracker-status-chunk.ts @@ -0,0 +1,20 @@ +/* eslint-disable no-case-declarations */ + +import { Decoders } from '..'; +import { DataTrackerStatusChunk, DataTrackerStatusChunkData } from '../../models/data/data-tracker-status-chunk'; + +export default (buffer: Uint8Array): DataTrackerStatusChunk => { + const chunk = Decoders.Chunk(buffer); + + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); + const validity = view.getFloat32(0, true); + + const data: DataTrackerStatusChunkData = { + validity, + }; + + return { + chunk, + data, + }; +}; diff --git a/src/decoders/data/data-tracker-timestamp-chunk.ts b/src/decoders/data/data-tracker-timestamp-chunk.ts new file mode 100644 index 0000000..f253454 --- /dev/null +++ b/src/decoders/data/data-tracker-timestamp-chunk.ts @@ -0,0 +1,23 @@ +/* eslint-disable no-case-declarations */ + +import { Decoders } from '..'; +import { + DataTrackerTimestampChunk, + DataTrackerTimestampChunkData, +} from '../../models/data/data-tracker-timestamp-chunk'; + +export default (buffer: Uint8Array): DataTrackerTimestampChunk => { + const chunk = Decoders.Chunk(buffer); + + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); + const timestamp = view.getBigUint64(0, true); + + const data: DataTrackerTimestampChunkData = { + timestamp, + }; + + return { + chunk, + data, + }; +}; diff --git a/src/decoders/data/data-tracker-xyz-chunk.ts b/src/decoders/data/data-tracker-xyz-chunk.ts new file mode 100644 index 0000000..00e6d32 --- /dev/null +++ b/src/decoders/data/data-tracker-xyz-chunk.ts @@ -0,0 +1,20 @@ +import { Decoders } from '..'; +import { DataTrackerXYZChunk, DataTrackerXYZChunkData } from '../../models/data/data-tracker-xyz-chunk'; + +export default (buffer: Uint8Array): DataTrackerXYZChunk => { + const chunk = Decoders.Chunk(buffer); + + // TODO(jwetzell): add error handling + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); + + const data: DataTrackerXYZChunkData = { + x: view.getFloat32(0, true), + y: view.getFloat32(4, true), + z: view.getFloat32(8, true), + }; + + return { + chunk, + data, + }; +}; diff --git a/src/decoders/index.ts b/src/decoders/index.ts index 4f5d7b5..a03df31 100644 --- a/src/decoders/index.ts +++ b/src/decoders/index.ts @@ -4,8 +4,10 @@ import PacketHeaderChunk from './packet-header-chunk'; import DataPacketChunk from './data/data-packet-chunk'; import DataTrackerChunk from './data/data-tracker-chunk'; -import DataTrackerFieldChunk from './data/data-tracker-field-chunk'; import DataTrackerListChunk from './data/data-tracker-list-chunk'; +import DataTrackerStatusChunk from './data/data-tracker-status-chunk'; +import DataTrackerTimestampChunk from './data/data-tracker-timestamp-chunk'; +import DataTrackerXYZChunk from './data/data-tracker-xyz-chunk'; import InfoPacketChunk from './info/info-packet-chunk'; import InfoSystemNameChunk from './info/info-system-name-chunk'; @@ -19,7 +21,9 @@ export const Decoders = { Packet, DataPacketChunk, DataTrackerChunk, - DataTrackerFieldChunk, + DataTrackerXYZChunk, + DataTrackerStatusChunk, + DataTrackerTimestampChunk, DataTrackerListChunk, InfoPacketChunk, InfoSystemNameChunk, diff --git a/src/decoders/info/info-packet-chunk.ts b/src/decoders/info/info-packet-chunk.ts index ac52ff0..e102d82 100644 --- a/src/decoders/info/info-packet-chunk.ts +++ b/src/decoders/info/info-packet-chunk.ts @@ -1,37 +1,37 @@ import { Decoders } from '..'; import { Constants } from '../../constants'; -import { InfoPacketChunk } from '../../models/info/info-packet-chunk'; +import { InfoPacketChunk, InfoPacketChunkData } from '../../models/info/info-packet-chunk'; -function decodeInfoPacketChunk(infoPacketChunk: InfoPacketChunk) { - if (infoPacketChunk.has_subchunks && infoPacketChunk.chunk_data && infoPacketChunk.data_len) { +export default (buffer: Uint8Array): InfoPacketChunk => { + const chunk = Decoders.Chunk(buffer); + + const data: InfoPacketChunkData = {}; + + if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) { let offset = 0; - while (offset < infoPacketChunk.data_len) { - const view = new DataView( - infoPacketChunk.chunk_data.buffer, - infoPacketChunk.chunk_data.byteOffset, - infoPacketChunk.chunk_data.byteLength - ); + while (offset < chunk.header.dataLen) { + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); const chunkId = view.getUint16(offset, true); switch (chunkId) { case 0x0000: - infoPacketChunk.packet_header = Decoders.PacketHeaderChunk(infoPacketChunk.chunk_data.slice(offset)); + data.packetHeader = Decoders.PacketHeaderChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (infoPacketChunk.packet_header?.data_len) { - offset += infoPacketChunk.packet_header.data_len; + if (data.packetHeader?.chunk.header.dataLen) { + offset += data.packetHeader.chunk.header.dataLen; } break; case 0x0001: - infoPacketChunk.system_name = Decoders.InfoSystemNameChunk(infoPacketChunk.chunk_data.slice(offset)); + data.systemName = Decoders.InfoSystemNameChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (infoPacketChunk.system_name?.data_len) { - offset += infoPacketChunk.system_name.data_len; + if (data.systemName?.chunk.header.dataLen) { + offset += data.systemName?.chunk.header.dataLen; } break; case 0x0002: - infoPacketChunk.tracker_list = Decoders.InfoTrackerListChunk(infoPacketChunk.chunk_data.slice(offset)); + data.trackerList = Decoders.InfoTrackerListChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (infoPacketChunk.tracker_list?.data_len) { - offset += infoPacketChunk.tracker_list.data_len; + if (data.trackerList?.chunk.header.dataLen) { + offset += data.trackerList.chunk.header.dataLen; } break; default: @@ -39,7 +39,9 @@ function decodeInfoPacketChunk(infoPacketChunk: InfoPacketChunk) { } } } -} -export default (buffer: Uint8Array): InfoPacketChunk => - Decoders.Chunk(buffer, decodeInfoPacketChunk) as InfoPacketChunk; + return { + chunk, + data, + }; +}; diff --git a/src/decoders/info/info-system-name-chunk.ts b/src/decoders/info/info-system-name-chunk.ts index d1d83be..0b46916 100644 --- a/src/decoders/info/info-system-name-chunk.ts +++ b/src/decoders/info/info-system-name-chunk.ts @@ -1,13 +1,15 @@ import { Decoders } from '..'; -import { InfoSystemNameChunk } from '../../models/info/info-system-name-chunk'; +import { InfoSystemNameChunk, InfoSystemNameChunkData } from '../../models/info/info-system-name-chunk'; -function decodeSystemNameChunk(systemNameChunk: InfoSystemNameChunk) { - if (systemNameChunk.chunk_data !== undefined && systemNameChunk.data_len !== undefined) { - systemNameChunk.system_name = new TextDecoder().decode( - systemNameChunk.chunk_data.slice(0, systemNameChunk.data_len) - ); - } -} +export default (buffer: Uint8Array): InfoSystemNameChunk => { + const chunk = Decoders.Chunk(buffer); -export default (buffer: Uint8Array): InfoSystemNameChunk => - Decoders.Chunk(buffer, decodeSystemNameChunk) as InfoSystemNameChunk; + const data: InfoSystemNameChunkData = { + systemName: new TextDecoder().decode(chunk.chunkData.subarray(0, chunk.header.dataLen)), + }; + + return { + chunk, + data, + }; +}; diff --git a/src/decoders/info/info-tracker-chunk.ts b/src/decoders/info/info-tracker-chunk.ts index ea4b456..fbc19e6 100644 --- a/src/decoders/info/info-tracker-chunk.ts +++ b/src/decoders/info/info-tracker-chunk.ts @@ -1,31 +1,36 @@ import { Decoders } from '..'; import { Constants } from '../../constants'; -import { InfoTrackerChunk } from '../../models/info/info-tracker-chunk'; +import { InfoTrackerChunk, InfoTrackerChunkData } from '../../models/info/info-tracker-chunk'; -function decodeInfoTrackerChunk(infoTrackerChunk: InfoTrackerChunk) { - if (infoTrackerChunk.has_subchunks && infoTrackerChunk.chunk_data && infoTrackerChunk.data_len) { +export default (buffer: Uint8Array): InfoTrackerChunk => { + const chunk = Decoders.Chunk(buffer); + + if (chunk.header.hasSubchunks && chunk.chunkData && chunk.header.dataLen) { let offset = 0; - while (offset < infoTrackerChunk.data_len) { - const view = new DataView( - infoTrackerChunk.chunk_data.buffer, - infoTrackerChunk.chunk_data.byteOffset, - infoTrackerChunk.chunk_data.byteLength - ); + while (offset < chunk.header.dataLen) { + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); const chunkId = view.getUint16(offset, true); switch (chunkId) { case 0x0000: - infoTrackerChunk.tracker_name = Decoders.InfoTrackerNameChunk(infoTrackerChunk.chunk_data.slice(offset)); + const data: InfoTrackerChunkData = { + trackerName: Decoders.InfoTrackerNameChunk(chunk.chunkData.subarray(offset)), + }; offset += Constants.CHUNK_HEADER_SIZE; - if (infoTrackerChunk.tracker_name?.data_len) { - offset += infoTrackerChunk?.tracker_name?.data_len; + if (data.trackerName.chunk.header.dataLen) { + offset += data.trackerName.chunk.header.dataLen; } - break; + return { + chunk, + data, + }; default: break; } } } -} -export default (buffer: Uint8Array): InfoTrackerChunk => Decoders.Chunk(buffer, decodeInfoTrackerChunk); + return { + chunk, + }; +}; diff --git a/src/decoders/info/info-tracker-list-chunk.ts b/src/decoders/info/info-tracker-list-chunk.ts index 402d978..e954d58 100644 --- a/src/decoders/info/info-tracker-list-chunk.ts +++ b/src/decoders/info/info-tracker-list-chunk.ts @@ -1,24 +1,33 @@ import { Decoders } from '..'; import { Constants } from '../../constants'; -import { InfoTrackerListChunk } from '../../models/info/info-tracker-list-chunk'; +import { InfoTrackerChunk } from '../../models/info/info-tracker-chunk'; +import { InfoTrackerListChunk, InfoTrackerListChunkData } from '../../models/info/info-tracker-list-chunk'; -function decodeInfoTrackerListChunk(infoTrackerListChunk: InfoTrackerListChunk) { - infoTrackerListChunk.trackers = {}; - if (infoTrackerListChunk.has_subchunks && infoTrackerListChunk.chunk_data) { +export default (buffer: Uint8Array): InfoTrackerListChunk => { + const chunk = Decoders.Chunk(buffer); + + const trackers: InfoTrackerChunk[] = []; + + if (chunk.header.hasSubchunks && chunk.chunkData) { let offset = 0; - if (infoTrackerListChunk.data_len) { - while (offset < infoTrackerListChunk.data_len) { - const trackerChunk = Decoders.InfoTrackerChunk(infoTrackerListChunk.chunk_data.slice(offset)); + if (chunk.header.dataLen) { + while (offset < chunk.header.dataLen) { + const trackerChunk = Decoders.InfoTrackerChunk(chunk.chunkData.subarray(offset)); offset += Constants.CHUNK_HEADER_SIZE; - if (trackerChunk.data_len) { - offset += trackerChunk.data_len; + if (trackerChunk.chunk.header.dataLen) { + offset += trackerChunk.chunk.header.dataLen; } - if (trackerChunk.id !== undefined) { - infoTrackerListChunk.trackers[trackerChunk.id] = trackerChunk; + if (trackerChunk.chunk.header.id !== undefined) { + trackers.push(trackerChunk); } } } } -} -export default (buffer: Uint8Array): InfoTrackerListChunk => - Decoders.Chunk(buffer, decodeInfoTrackerListChunk) as InfoTrackerListChunk; + const data: InfoTrackerListChunkData = { + trackers, + }; + return { + chunk, + data, + }; +}; diff --git a/src/decoders/info/info-tracker-name-chunk.ts b/src/decoders/info/info-tracker-name-chunk.ts index 315ad05..3d8be6f 100644 --- a/src/decoders/info/info-tracker-name-chunk.ts +++ b/src/decoders/info/info-tracker-name-chunk.ts @@ -1,12 +1,15 @@ import { Decoders } from '..'; -import { InfoTrackerNameChunk } from '../../models/info/info-tracker-name-chunk'; +import { InfoTrackerNameChunk, InfoTrackerNameChunkData } from '../../models/info/info-tracker-name-chunk'; -function decodeTrackerNameChunk(trackerNameChunk: InfoTrackerNameChunk) { - if (trackerNameChunk.chunk_data !== undefined && trackerNameChunk.data_len !== undefined) { - trackerNameChunk.tracker_name = new TextDecoder().decode( - trackerNameChunk.chunk_data.slice(0, trackerNameChunk.data_len) - ); - } -} -export default (buffer: Uint8Array): InfoTrackerNameChunk => - Decoders.Chunk(buffer, decodeTrackerNameChunk) as InfoTrackerNameChunk; +export default (buffer: Uint8Array): InfoTrackerNameChunk => { + const chunk = Decoders.Chunk(buffer); + + const data: InfoTrackerNameChunkData = { + trackerName: new TextDecoder().decode(chunk.chunkData.subarray(0, chunk.header.dataLen)), + }; + + return { + chunk, + data, + }; +}; diff --git a/src/decoders/packet-header-chunk.ts b/src/decoders/packet-header-chunk.ts index df66100..5919985 100644 --- a/src/decoders/packet-header-chunk.ts +++ b/src/decoders/packet-header-chunk.ts @@ -1,21 +1,20 @@ import { Decoders } from '.'; -import { PacketHeaderChunk } from '../models/packet-header-chunk'; - -function decodePacketHeaderChunk(packetHeaderChunk: PacketHeaderChunk) { - if (packetHeaderChunk.chunk_data) { - const view = new DataView( - packetHeaderChunk.chunk_data.buffer, - packetHeaderChunk.chunk_data.byteOffset, - packetHeaderChunk.chunk_data.byteLength - ); - packetHeaderChunk.packet_timestamp = view.getBigUint64(0, true); - packetHeaderChunk.version_high = view.getUint8(8); - packetHeaderChunk.version_low = view.getUint8(9); - packetHeaderChunk.frame_id = view.getUint8(10); - packetHeaderChunk.frame_packet_count = view.getUint8(11); - } -} +import { PacketHeaderChunk, PacketHeaderChunkData } from '../models/packet-header-chunk'; export default (buffer: Uint8Array): PacketHeaderChunk => { - return Decoders.Chunk(buffer, decodePacketHeaderChunk); + const chunk = Decoders.Chunk(buffer); + + const view = new DataView(chunk.chunkData.buffer, chunk.chunkData.byteOffset, chunk.chunkData.byteLength); + const data: PacketHeaderChunkData = { + packetTimestamp: view.getBigUint64(0, true), + versionHigh: chunk.chunkData[8], + versionLow: chunk.chunkData[9], + frameId: chunk.chunkData[10], + framePacketCount: chunk.chunkData[11], + }; + + return { + chunk, + data, + }; }; diff --git a/src/models/chunk.ts b/src/models/chunk.ts index 7a40c61..f3ba498 100644 --- a/src/models/chunk.ts +++ b/src/models/chunk.ts @@ -1,6 +1,10 @@ -export interface Chunk { - id?: number; - has_subchunks?: boolean; - data_len?: number; - chunk_data?: Uint8Array; +export interface ChunkHeader { + id: number; + dataLen: number; + hasSubchunks: boolean; +} + +export interface Chunk { + chunkData: Uint8Array; + header: ChunkHeader; } diff --git a/src/models/data/data-packet-chunk.ts b/src/models/data/data-packet-chunk.ts index 34ea8f0..eed190b 100644 --- a/src/models/data/data-packet-chunk.ts +++ b/src/models/data/data-packet-chunk.ts @@ -2,7 +2,12 @@ import { Chunk } from '../chunk'; import { PacketHeaderChunk } from '../packet-header-chunk'; import { DataTrackerListChunk } from './data-tracker-list-chunk'; -export interface DataPacketChunk extends Chunk { - packet_header: PacketHeaderChunk; - tracker_list: DataTrackerListChunk; +export interface DataPacketChunkData { + packetHeader?: PacketHeaderChunk; + trackerList?: DataTrackerListChunk; +} + +export interface DataPacketChunk { + chunk: Chunk; + data: DataPacketChunkData; } diff --git a/src/models/data/data-tracker-chunk.ts b/src/models/data/data-tracker-chunk.ts index 3d44932..a889ee6 100644 --- a/src/models/data/data-tracker-chunk.ts +++ b/src/models/data/data-tracker-chunk.ts @@ -1,12 +1,19 @@ import { Chunk } from '../chunk'; -import { DataTrackerFieldChunk } from './data-tracker-field-chunk'; +import { DataTrackerStatusChunk } from './data-tracker-status-chunk'; +import { DataTrackerTimestampChunk } from './data-tracker-timestamp-chunk'; +import { DataTrackerXYZChunk } from './data-tracker-xyz-chunk'; -export interface DataTrackerChunk extends Chunk { - pos?: DataTrackerFieldChunk; - speed?: DataTrackerFieldChunk; - ori?: DataTrackerFieldChunk; - status?: DataTrackerFieldChunk; - accel?: DataTrackerFieldChunk; - trgtpos?: DataTrackerFieldChunk; - timestamp?: DataTrackerFieldChunk; +export interface DataTrackerChunkData { + pos?: DataTrackerXYZChunk; + speed?: DataTrackerXYZChunk; + ori?: DataTrackerXYZChunk; + status?: DataTrackerStatusChunk; + accel?: DataTrackerXYZChunk; + trgtpos?: DataTrackerXYZChunk; + timestamp?: DataTrackerTimestampChunk; +} + +export interface DataTrackerChunk { + chunk: Chunk; + data: DataTrackerChunkData; } diff --git a/src/models/data/data-tracker-field-chunk.ts b/src/models/data/data-tracker-field-chunk.ts deleted file mode 100644 index f0e5cf3..0000000 --- a/src/models/data/data-tracker-field-chunk.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Chunk } from '../chunk'; - -export interface DataTrackerFieldChunk extends Chunk { - [key: string]: number | bigint | number[] | Uint8Array | undefined | boolean; -} diff --git a/src/models/data/data-tracker-list-chunk.ts b/src/models/data/data-tracker-list-chunk.ts index 006ace2..67609a6 100644 --- a/src/models/data/data-tracker-list-chunk.ts +++ b/src/models/data/data-tracker-list-chunk.ts @@ -1,8 +1,11 @@ import { Chunk } from '../chunk'; import { DataTrackerChunk } from './data-tracker-chunk'; -export interface DataTrackerListChunk extends Chunk { - trackers: { - [key: number]: DataTrackerChunk; - }; +export interface DataTrackerListChunkData { + trackers: DataTrackerChunk[]; +} + +export interface DataTrackerListChunk { + chunk: Chunk; + data: DataTrackerListChunkData; } diff --git a/src/models/data/data-tracker-status-chunk.ts b/src/models/data/data-tracker-status-chunk.ts new file mode 100644 index 0000000..6f84b3e --- /dev/null +++ b/src/models/data/data-tracker-status-chunk.ts @@ -0,0 +1,10 @@ +import { Chunk } from '../chunk'; + +export interface DataTrackerStatusChunkData { + validity: number; +} + +export interface DataTrackerStatusChunk { + chunk: Chunk; + data: DataTrackerStatusChunkData; +} diff --git a/src/models/data/data-tracker-timestamp-chunk.ts b/src/models/data/data-tracker-timestamp-chunk.ts new file mode 100644 index 0000000..9fb9813 --- /dev/null +++ b/src/models/data/data-tracker-timestamp-chunk.ts @@ -0,0 +1,10 @@ +import { Chunk } from '../chunk'; + +export interface DataTrackerTimestampChunkData { + timestamp: bigint; +} + +export interface DataTrackerTimestampChunk { + chunk: Chunk; + data: DataTrackerTimestampChunkData; +} diff --git a/src/models/data/data-tracker-xyz-chunk.ts b/src/models/data/data-tracker-xyz-chunk.ts new file mode 100644 index 0000000..6800ce0 --- /dev/null +++ b/src/models/data/data-tracker-xyz-chunk.ts @@ -0,0 +1,12 @@ +import { Chunk } from '../chunk'; + +export interface DataTrackerXYZChunkData { + x: number; + y: number; + z: number; +} + +export interface DataTrackerXYZChunk { + chunk: Chunk; + data: DataTrackerXYZChunkData; +} diff --git a/src/models/index.ts b/src/models/index.ts index 599df32..98db773 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,7 +1,6 @@ export * from './chunk'; export * from './data/data-packet-chunk'; export * from './data/data-tracker-chunk'; -export * from './data/data-tracker-field-chunk'; export * from './data/data-tracker-list-chunk'; export * from './info/info-packet-chunk'; export * from './info/info-system-name-chunk'; diff --git a/src/models/info/info-packet-chunk.ts b/src/models/info/info-packet-chunk.ts index f7b5c53..2f72578 100644 --- a/src/models/info/info-packet-chunk.ts +++ b/src/models/info/info-packet-chunk.ts @@ -3,8 +3,12 @@ import { PacketHeaderChunk } from '../packet-header-chunk'; import { InfoSystemNameChunk } from './info-system-name-chunk'; import { InfoTrackerListChunk } from './info-tracker-list-chunk'; -export interface InfoPacketChunk extends Chunk { - packet_header: PacketHeaderChunk; - system_name: InfoSystemNameChunk; - tracker_list: InfoTrackerListChunk; +export interface InfoPacketChunkData { + packetHeader?: PacketHeaderChunk; + systemName?: InfoSystemNameChunk; + trackerList?: InfoTrackerListChunk; +} +export interface InfoPacketChunk { + chunk: Chunk; + data: InfoPacketChunkData; } diff --git a/src/models/info/info-system-name-chunk.ts b/src/models/info/info-system-name-chunk.ts index 400565a..f443a79 100644 --- a/src/models/info/info-system-name-chunk.ts +++ b/src/models/info/info-system-name-chunk.ts @@ -1,5 +1,10 @@ import { Chunk } from '../chunk'; -export interface InfoSystemNameChunk extends Chunk { - system_name: string; +export interface InfoSystemNameChunkData { + systemName: string; +} + +export interface InfoSystemNameChunk { + chunk: Chunk; + data: InfoSystemNameChunkData; } diff --git a/src/models/info/info-tracker-chunk.ts b/src/models/info/info-tracker-chunk.ts index 397be42..7f745d8 100644 --- a/src/models/info/info-tracker-chunk.ts +++ b/src/models/info/info-tracker-chunk.ts @@ -1,6 +1,11 @@ import { Chunk } from '../chunk'; import { InfoTrackerNameChunk } from './info-tracker-name-chunk'; -export interface InfoTrackerChunk extends Chunk { - tracker_name?: InfoTrackerNameChunk; +export interface InfoTrackerChunkData { + trackerName: InfoTrackerNameChunk; +} + +export interface InfoTrackerChunk { + chunk: Chunk; + data?: InfoTrackerChunkData; } diff --git a/src/models/info/info-tracker-list-chunk.ts b/src/models/info/info-tracker-list-chunk.ts index 8cbf810..92ab85f 100644 --- a/src/models/info/info-tracker-list-chunk.ts +++ b/src/models/info/info-tracker-list-chunk.ts @@ -1,8 +1,11 @@ import { Chunk } from '../chunk'; import { InfoTrackerChunk } from './info-tracker-chunk'; -export interface InfoTrackerListChunk extends Chunk { - trackers: { - [key: number]: InfoTrackerChunk; - }; +export interface InfoTrackerListChunkData { + trackers: InfoTrackerChunk[]; +} + +export interface InfoTrackerListChunk { + chunk: Chunk; + data: InfoTrackerListChunkData; } diff --git a/src/models/info/info-tracker-name-chunk.ts b/src/models/info/info-tracker-name-chunk.ts index 2a5b4bd..5ad66de 100644 --- a/src/models/info/info-tracker-name-chunk.ts +++ b/src/models/info/info-tracker-name-chunk.ts @@ -1,5 +1,10 @@ import { Chunk } from '../chunk'; -export interface InfoTrackerNameChunk extends Chunk { - tracker_name: string; +export interface InfoTrackerNameChunkData { + trackerName: string; +} + +export interface InfoTrackerNameChunk { + chunk: Chunk; + data: InfoTrackerNameChunkData; } diff --git a/src/models/packet-header-chunk.ts b/src/models/packet-header-chunk.ts index 7db2add..6b581fd 100644 --- a/src/models/packet-header-chunk.ts +++ b/src/models/packet-header-chunk.ts @@ -1,9 +1,14 @@ import { Chunk } from './chunk'; -export interface PacketHeaderChunk extends Chunk { - packet_timestamp?: bigint; - version_high?: number; - version_low?: number; - frame_id?: number; - frame_packet_count?: number; +export interface PacketHeaderChunkData { + packetTimestamp: bigint; + versionHigh: number; + versionLow: number; + frameId: number; + framePacketCount: number; +} + +export interface PacketHeaderChunk { + chunk: Chunk; + data: PacketHeaderChunkData; } diff --git a/src/models/tracker.ts b/src/models/tracker.ts index df28d76..74bc387 100644 --- a/src/models/tracker.ts +++ b/src/models/tracker.ts @@ -8,16 +8,24 @@ import dataTrackerTimestampChunk from '../encoders/data/data-tracker-timestamp-c import dataTrackerTrgtposChunk from '../encoders/data/data-tracker-trgtpos-chunk'; import infoTrackerChunk from '../encoders/info/info-tracker-chunk'; import infoTrackerNameChunk from '../encoders/info/info-tracker-name-chunk'; +import { DataTrackerChunk } from './data/data-tracker-chunk'; +import { InfoTrackerChunk } from './info/info-tracker-chunk'; + +export type XYZData = { + x: number; + y: number; + z: number; +}; export class Tracker { id: number; name: string; - pos?: [number, number, number]; - speed?: [number, number, number]; - ori?: [number, number, number]; + pos?: XYZData; + speed?: XYZData; + ori?: XYZData; validity?: number; - accel?: [number, number, number]; - trgtpos?: [number, number, number]; + accel?: XYZData; + trgtpos?: XYZData; timestamp?: bigint; constructor(id: number, name: string) { @@ -33,15 +41,45 @@ export class Tracker { } setPos(x: number, y: number, z: number) { - this.pos = [x, y, z]; + if (this.pos === undefined) { + this.pos = { + x, + y, + z, + }; + } else { + this.pos.x = x; + this.pos.y = y; + this.pos.z = z; + } } setSpeed(x: number, y: number, z: number) { - this.speed = [x, y, z]; + if (this.speed === undefined) { + this.speed = { + x, + y, + z, + }; + } else { + this.speed.x = x; + this.speed.y = y; + this.speed.z = z; + } } setOri(x: number, y: number, z: number) { - this.ori = [x, y, z]; + if (this.ori === undefined) { + this.ori = { + x, + y, + z, + }; + } else { + this.ori.x = x; + this.ori.y = y; + this.ori.z = z; + } } setStatus(validity: number) { @@ -49,11 +87,31 @@ export class Tracker { } setAccel(x: number, y: number, z: number) { - this.accel = [x, y, z]; + if (this.accel === undefined) { + this.accel = { + x, + y, + z, + }; + } else { + this.accel.x = x; + this.accel.y = y; + this.accel.z = z; + } } setTrgtPos(x: number, y: number, z: number) { - this.trgtpos = [x, y, z]; + if (this.trgtpos === undefined) { + this.trgtpos = { + x, + y, + z, + }; + } else { + this.trgtpos.x = x; + this.trgtpos.y = y; + this.trgtpos.z = z; + } } setTimestamp(timestamp: bigint) { @@ -64,15 +122,15 @@ export class Tracker { const fieldChunks: Uint8Array[] = []; if (this.pos) { - fieldChunks.push(dataTrackerPosChunk(...this.pos)); + fieldChunks.push(dataTrackerPosChunk(this.pos.x, this.pos.y, this.pos.z)); } if (this.speed) { - fieldChunks.push(dataTrackerSpeedChunk(...this.speed)); + fieldChunks.push(dataTrackerSpeedChunk(this.speed.x, this.speed.y, this.speed.z)); } if (this.ori) { - fieldChunks.push(dataTrackerOriChunk(...this.ori)); + fieldChunks.push(dataTrackerOriChunk(this.ori.x, this.ori.y, this.ori.z)); } if (this.validity) { @@ -80,11 +138,11 @@ export class Tracker { } if (this.accel) { - fieldChunks.push(dataTrackerAccelChunk(...this.accel)); + fieldChunks.push(dataTrackerAccelChunk(this.accel.x, this.accel.y, this.accel.z)); } if (this.trgtpos) { - fieldChunks.push(dataTrackerTrgtposChunk(...this.trgtpos)); + fieldChunks.push(dataTrackerTrgtposChunk(this.trgtpos.x, this.trgtpos.y, this.trgtpos.z)); } if (this.timestamp) { @@ -97,4 +155,68 @@ export class Tracker { getInfoChunk() { return infoTrackerChunk(this.id, infoTrackerNameChunk(this.name)); } + + updateInfo(infoTrackerChunk: InfoTrackerChunk) { + if (infoTrackerChunk.data) { + this.name = infoTrackerChunk.data.trackerName.data.trackerName; + } + } + + updateData(dataTrackerChunk: DataTrackerChunk) { + if (dataTrackerChunk.data.pos) { + this.setPos(dataTrackerChunk.data.pos.data.x, dataTrackerChunk.data.pos.data.y, dataTrackerChunk.data.pos.data.z); + } + + if (dataTrackerChunk.data.speed) { + this.setSpeed( + dataTrackerChunk.data.speed.data.x, + dataTrackerChunk.data.speed.data.y, + dataTrackerChunk.data.speed.data.z + ); + } + + if (dataTrackerChunk.data.ori) { + this.setOri(dataTrackerChunk.data.ori.data.x, dataTrackerChunk.data.ori.data.y, dataTrackerChunk.data.ori.data.z); + } + + if (dataTrackerChunk.data.status) { + this.setStatus(dataTrackerChunk.data.status.data.validity); + } + + if (dataTrackerChunk.data.accel) { + this.setAccel( + dataTrackerChunk.data.accel.data.x, + dataTrackerChunk.data.accel.data.y, + dataTrackerChunk.data.accel.data.z + ); + } + + if (dataTrackerChunk.data.trgtpos) { + this.setTrgtPos( + dataTrackerChunk.data.trgtpos.data.x, + dataTrackerChunk.data.trgtpos.data.y, + dataTrackerChunk.data.trgtpos.data.z + ); + } + + if (dataTrackerChunk.data.timestamp) { + this.setTimestamp(dataTrackerChunk.data.timestamp.data.timestamp); + } + } +} + +export function TrackerFromInfo(infoTrackerChunk: InfoTrackerChunk) { + if (infoTrackerChunk.data) { + return new Tracker(infoTrackerChunk.chunk.header.id, infoTrackerChunk.data.trackerName.data.trackerName); + } + return undefined; +} + +export function TrackerFromData(dataTrackerChunk: DataTrackerChunk) { + if (dataTrackerChunk.data) { + const tracker = new Tracker(dataTrackerChunk.chunk.header.id, ''); + tracker.updateData(dataTrackerChunk); + return tracker; + } + return undefined; }