diff --git a/src/decoders/index.ts b/src/decoders/index.ts index ea9be20..0b1d7dd 100644 --- a/src/decoders/index.ts +++ b/src/decoders/index.ts @@ -1,4 +1,5 @@ import ChannelBlock from './lighting/channel-block'; +import Spot from './lighting/spot'; import CentroidAccelVelocity from './motion/centroid-accel-velocity'; import CentroidPosition from './motion/centroid-position'; import OrientationEuler from './motion/orientation-euler'; @@ -23,5 +24,6 @@ export const Decoders = { OrientationEuler, ZoneCollisionDetection, ZoneObject, + Spot, ChannelBlock, }; diff --git a/src/decoders/lighting/spot.ts b/src/decoders/lighting/spot.ts new file mode 100644 index 0000000..3d9c0d2 --- /dev/null +++ b/src/decoders/lighting/spot.ts @@ -0,0 +1,44 @@ +import { Decoders } from '..'; +import { ChannelBlock, Spot } from '../../models'; + +export default (bytes: Uint8Array, isLittleEndian: boolean = false): Spot => { + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + + let dataOffset = 0; + const type = view.getUint8(dataOffset); + dataOffset += 1; + if (type !== 0x0a) { + throw new Error('Spot module must have a type of 0x0a'); + } + + const size = view.getUint16(dataOffset, isLittleEndian); + dataOffset += 2; + if (size !== bytes.byteLength) { + throw new Error('Spot module size mismatch'); + } + const id = view.getUint16(dataOffset, isLittleEndian); + dataOffset += 2; + const offset = view.getUint16(dataOffset, isLittleEndian); + dataOffset += 2; + const numberOfChannelBlocks = view.getUint16(dataOffset, isLittleEndian); + dataOffset += 2; + + const channelBlocks: ChannelBlock[] = []; + let zoneObjectOffset = dataOffset; + + for (let index = 0; index < numberOfChannelBlocks; index++) { + const channelBlockData = bytes.subarray(zoneObjectOffset, zoneObjectOffset + 5); + console.log(channelBlockData); + const channelBlock = Decoders.ChannelBlock(channelBlockData); + channelBlocks.push(channelBlock); + zoneObjectOffset += channelBlockData.byteLength; + } + return { + type, + size, + id, + offset, + numberOfChannelBlocks, + channelBlocks, + }; +}; diff --git a/src/models.ts b/src/models.ts index 871cf42..aaef772 100644 --- a/src/models.ts +++ b/src/models.ts @@ -115,6 +115,15 @@ export type ZoneObject = { name: string; }; +export type Spot = { + type: number; + size: number; + id: number; + offset: number; + numberOfChannelBlocks: number; + channelBlocks: ChannelBlock[]; +}; + export type ChannelBlock = { offset: number; fade: number; diff --git a/tests/decode.test.js b/tests/decode.test.js index 3d90dca..72fed4c 100644 --- a/tests/decode.test.js +++ b/tests/decode.test.js @@ -251,6 +251,25 @@ const goodTests = [ }, decoder: Decoders.RTTrPM, }, + { + description: 'Spot + Single Channel Block', + bytes: new Uint8Array([0x0a, 0x00, 0x0e, 0x12, 0x34, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x06, 0x40]), + expected: { + type: 0x0a, + size: 14, + id: 0x1234, + offset: 1, + numberOfChannelBlocks: 1, + channelBlocks: [ + { + offset: 0x08, + fade: 0x06, + value: 0x40, + }, + ], + }, + decoder: Decoders.Spot, + }, { description: 'Channel Block', bytes: new Uint8Array([0x00, 0x08, 0x00, 0x06, 0x40]),