From 60dd1499186f0af50047e0fe1cb676abe455cd8f Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Sat, 15 Mar 2025 12:23:40 -0500 Subject: [PATCH] add decoder for lighting output --- src/decoders/index.ts | 2 ++ src/decoders/lighting/lighting-output.ts | 46 ++++++++++++++++++++++++ src/decoders/lighting/universe.ts | 2 +- src/models.ts | 10 ++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/decoders/lighting/lighting-output.ts diff --git a/src/decoders/index.ts b/src/decoders/index.ts index e8fcb4a..21f1406 100644 --- a/src/decoders/index.ts +++ b/src/decoders/index.ts @@ -1,4 +1,5 @@ import ChannelBlock from './lighting/channel-block'; +import LightingOutput from './lighting/lighting-output'; import Spot from './lighting/spot'; import Universe from './lighting/universe'; import CentroidAccelVelocity from './motion/centroid-accel-velocity'; @@ -28,4 +29,5 @@ export const Decoders = { Spot, ChannelBlock, Universe, + LightingOutput, }; diff --git a/src/decoders/lighting/lighting-output.ts b/src/decoders/lighting/lighting-output.ts new file mode 100644 index 0000000..f0bd5c6 --- /dev/null +++ b/src/decoders/lighting/lighting-output.ts @@ -0,0 +1,46 @@ +import { Decoders } from '..'; +import { LightingOutput, Universe } from '../../models'; + +export default (bytes: Uint8Array, isLittleEndian: boolean = false): LightingOutput => { + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + + let dataOffset = 0; + const type = view.getUint8(dataOffset); + dataOffset += 1; + if (type !== 0x07) { + throw new Error('Lighting Output module must have a type of 0x09'); + } + + const size = view.getUint16(dataOffset, isLittleEndian); + dataOffset += 2; + if (size < bytes.byteLength) { + throw new Error('Lighting Output module size mismatch'); + } + const sequence = view.getUint32(dataOffset, isLittleEndian); + dataOffset += 4; + const action = view.getUint8(dataOffset); + dataOffset += 1; + const holdTime = view.getUint32(dataOffset, isLittleEndian); + dataOffset += 4; + const numberOfUniverses = view.getUint16(dataOffset, isLittleEndian); + dataOffset += 2; + + const universes: Universe[] = []; + let universeOffset = dataOffset; + + for (let index = 0; index < numberOfUniverses; index++) { + const universeData = bytes.subarray(universeOffset); + const universe = Decoders.Universe(universeData); + universes.push(universe); + universeOffset += universe.size; + } + return { + type, + size, + sequence, + action, + holdTime, + numberOfUniverses, + universes, + }; +}; diff --git a/src/decoders/lighting/universe.ts b/src/decoders/lighting/universe.ts index ec9cc7b..392dbe8 100644 --- a/src/decoders/lighting/universe.ts +++ b/src/decoders/lighting/universe.ts @@ -13,7 +13,7 @@ export default (bytes: Uint8Array, isLittleEndian: boolean = false): Universe => const size = view.getUint16(dataOffset, isLittleEndian); dataOffset += 2; - if (size !== bytes.byteLength) { + if (size < bytes.byteLength) { throw new Error('Universe module size mismatch'); } const id = view.getUint16(dataOffset, isLittleEndian); diff --git a/src/models.ts b/src/models.ts index dc55bde..949430b 100644 --- a/src/models.ts +++ b/src/models.ts @@ -115,6 +115,16 @@ export type ZoneObject = { name: string; }; +export type LightingOutput = { + type: number; + size: number; + sequence: number; + action: number; + holdTime: number; + numberOfUniverses: number; + universes: Universe[]; +}; + export type Universe = { type: number; size: number;