UNPKG

lifxlan

Version:

TypeScript library for controlling LIFX products over LAN

935 lines 35.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPayload = exports.getHeaderSequence = exports.getHeaderType = exports.getHeaderAcknowledgeRequired = exports.getHeaderResponseRequired = exports.getHeaderResponseFlags = exports.getHeaderTarget = exports.getHeaderSource = exports.getHeaderTagged = exports.getHeaderFlags = exports.getHeaderSize = void 0; exports.encode = encode; exports.encodeUuidTo = encodeUuidTo; exports.encodeStringTo = encodeStringTo; exports.encodeString = encodeString; exports.encodeTimestampTo = encodeTimestampTo; exports.decodeStateService = decodeStateService; exports.decodeStateHostFirmware = decodeStateHostFirmware; exports.decodeStateWifiInfo = decodeStateWifiInfo; exports.decodeStateWifiFirmware = decodeStateWifiFirmware; exports.decodeStatePower = decodeStatePower; exports.decodeStateLabel = decodeStateLabel; exports.decodeStateVersion = decodeStateVersion; exports.decodeStateInfo = decodeStateInfo; exports.decodeStateLocation = decodeStateLocation; exports.decodeStateGroup = decodeStateGroup; exports.decodeEchoResponse = decodeEchoResponse; exports.decodeStateUnhandled = decodeStateUnhandled; exports.decodeSetColor = decodeSetColor; exports.encodeSetColor = encodeSetColor; exports.encodeSetPower = encodeSetPower; exports.encodeSetLocation = encodeSetLocation; exports.encodeSetGroup = encodeSetGroup; exports.encodeEchoRequest = encodeEchoRequest; exports.encodeSetWaveform = encodeSetWaveform; exports.encodeSetLightPower = encodeSetLightPower; exports.encodeSetWaveformOptional = encodeSetWaveformOptional; exports.encodeSetInfrared = encodeSetInfrared; exports.encodeSetHevCycle = encodeSetHevCycle; exports.encodeSetHevCycleConfiguration = encodeSetHevCycleConfiguration; exports.encodeGetRPower = encodeGetRPower; exports.encodeSetRPower = encodeSetRPower; exports.encodeGet64 = encodeGet64; exports.encodeGetColorZones = encodeGetColorZones; exports.encodeSetColorZones = encodeSetColorZones; exports.encodeSetMultiZoneEffect = encodeSetMultiZoneEffect; exports.encodeSetExtendedColorZones = encodeSetExtendedColorZones; exports.encodeSetUserPosition = encodeSetUserPosition; exports.encodeSet64 = encodeSet64; exports.encodeGetTileEffect = encodeGetTileEffect; exports.encodeSetTileEffect = encodeSetTileEffect; exports.decodeLightState = decodeLightState; exports.decodeStateLightPower = decodeStateLightPower; exports.decodeStateInfrared = decodeStateInfrared; exports.decodeStateHevCycle = decodeStateHevCycle; exports.decodeStateHevCycleConfiguration = decodeStateHevCycleConfiguration; exports.decodeStateLastHevCycleResult = decodeStateLastHevCycleResult; exports.decodeStateRPower = decodeStateRPower; exports.decodeStateDeviceChain = decodeStateDeviceChain; exports.decodeState64 = decodeState64; exports.decodeStateZone = decodeStateZone; exports.decodeStateMultiZone = decodeStateMultiZone; exports.decodeStateMultiZoneEffect = decodeStateMultiZoneEffect; exports.decodeStateExtendedColorZones = decodeStateExtendedColorZones; exports.decodeStateTileEffect = decodeStateTileEffect; exports.decodeSensorStateAmbientLight = decodeSensorStateAmbientLight; exports.decodeHeader = decodeHeader; /** * Encodes a LIFX protocol message into a binary format. * * This is the core encoding function that creates properly formatted LIFX LAN protocol messages. * The encoding follows the official LIFX protocol specification with optimized binary operations. */ function encode(tagged, source, target, resRequired, ackRequired, sequence, type, payload) { const protocol = 1024; const addressable = 1; const origin = 0; const size = 36 + (payload != null ? payload.byteLength : 0); const bytes = new Uint8Array(size); const view = new DataView(bytes.buffer, bytes.byteOffset); /** Frame Header */ view.setUint16(0, size, true); view.setUint16(2, protocol | (addressable << 12) | (+tagged << 13) | (origin << 14), true); view.setUint32(4, source, true); /** Frame Address */ bytes.set(target, 8); view.setUint8(22, ((resRequired ? 1 : 0) << 0) | ((ackRequired ? 1 : 0) << 1)); view.setUint8(23, sequence); /** Protocol Header */ // type view.setUint16(32, type, true); if (payload) { bytes.set(payload, 36); } return bytes; } /** * Encodes a UUID string directly into a byte array at the specified offset. * * Efficiently converts UUID format (e.g., "550e8400-e29b-41d4-a716-446655440000") * into 16 bytes at the target location. Optimized for minimal string allocations. */ function encodeUuidTo(bytes, offset, uuid) { const hex = uuid.replace(/-/g, ''); for (let i = 0, j = 0; i < hex.length; i += 2, j++) { bytes[offset + j] = parseInt(hex.slice(i, i + 2), 16); } } const textEncoder = new TextEncoder(); function encodeStringTo(bytes, offset, value, byteLength) { textEncoder.encodeInto(value, offset > 0 ? bytes.subarray(offset) : bytes); if (value.length < byteLength) { bytes[offset + value.length] = 0; } } function encodeString(value, byteLength) { const bytes = new Uint8Array(byteLength); encodeStringTo(bytes, 0, value, byteLength); return bytes; } function decodeBytes(bytes, offsetRef, byteLength) { const subarray = bytes.subarray(offsetRef.current, offsetRef.current + byteLength); offsetRef.current += byteLength; return subarray; } function decodeUuid(bytes, offsetRef) { return Array.from(decodeBytes(bytes, offsetRef, 16)).map((byte) => byte.toString(16).padStart(2, '0')).join(''); } const textDecoder = new TextDecoder(); function decodeString(bytes, offsetRef, maxLength) { let end = offsetRef.current; while (end < offsetRef.current + maxLength && bytes[end] !== 0) { end++; } const value = textDecoder.decode(bytes.subarray(offsetRef.current, end)); offsetRef.current += maxLength; return value; } function encodeTimestampTo(view, offset, date) { view.setBigUint64(offset, BigInt(date.getTime()) * 1000000n, true); } function decodeTimestamp(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const time = new Date(Number(view.getBigUint64(offsetRef.current, true) / 1000000n)); offsetRef.current += 8; return time; } function decodeStateService(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const service = view.getUint8(offsetRef.current); offsetRef.current += 1; const port = view.getUint32(offsetRef.current, true); offsetRef.current += 4; return { service, port, }; } function decodeStateHostFirmware(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const build = decodeTimestamp(bytes, offsetRef); const reserved = decodeBytes(bytes, offsetRef, 8); const version_minor = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const version_major = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return { build, reserved, version_minor, version_major, }; } function decodeStateWifiInfo(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const signal = view.getFloat32(offsetRef.current, true); offsetRef.current += 4; const reserved6 = decodeBytes(bytes, offsetRef, 4); const reserved7 = decodeBytes(bytes, offsetRef, 4); const reserved8 = decodeBytes(bytes, offsetRef, 2); return { signal, reserved6, reserved7, reserved8, }; } function decodeStateWifiFirmware(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); const build = decodeTimestamp(bytes, offsetRef); const reserved6 = decodeBytes(bytes, offsetRef, 8); const version_minor = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const version_major = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return { build, reserved6, version_minor, version_major, }; } function decodeStatePower(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const power = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return power; } function decodeStateLabel(bytes, offsetRef) { return decodeString(bytes, offsetRef, 32); } function decodeStateVersion(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const vendor = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const product = view.getUint32(offsetRef.current, true); offsetRef.current += 4; return { vendor, product, }; } function decodeStateInfo(bytes, offsetRef) { const time = decodeTimestamp(bytes, offsetRef); const uptime = decodeTimestamp(bytes, offsetRef); const downtime = decodeTimestamp(bytes, offsetRef); return { time, uptime, downtime, }; } function decodeStateLocation(bytes, offsetRef) { const location = decodeBytes(bytes, offsetRef, 16); const label = decodeString(bytes, offsetRef, 32); const updated_at = decodeTimestamp(bytes, offsetRef); return { location, label, updated_at, }; } function decodeStateGroup(bytes, offsetRef) { const group = decodeUuid(bytes, offsetRef); const label = decodeString(bytes, offsetRef, 32); const updated_at = decodeTimestamp(bytes, offsetRef); return { group, label, updated_at, }; } function decodeEchoResponse(bytes, offsetRef) { const payload = decodeBytes(bytes, offsetRef, 64); return payload; } function decodeStateUnhandled(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const type = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return type; } function decodeSetColor(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const reserved = decodeBytes(bytes, offsetRef, 1); const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const duration = view.getUint32(offsetRef.current, true); offsetRef.current += 4; return { reserved, hue, saturation, brightness, kelvin, duration, }; } function encodeSetColor(hue, saturation, brightness, kelvin, duration) { const payload = new Uint8Array(13); const view = new DataView(payload.buffer); view.setUint16(1, hue, true); view.setUint16(3, saturation, true); view.setUint16(5, brightness, true); view.setUint16(7, kelvin, true); view.setUint32(9, duration, true); return payload; } function encodeSetPower(power) { const payload = new Uint8Array(2); const view = new DataView(payload.buffer); view.setUint16(0, typeof power === 'number' ? power : power ? 65535 : 0, true); return payload; } function encodeSetLocation(location, label, updatedAt) { const payload = new Uint8Array(56); const view = new DataView(payload.buffer); if (typeof location === 'string') { encodeUuidTo(payload, 0, location); } else { payload.set(location, 0); } encodeStringTo(payload, 16, label, 32); encodeTimestampTo(view, 48, updatedAt); return payload; } function encodeSetGroup(group, label, updatedAt) { const payload = new Uint8Array(56); const view = new DataView(payload.buffer); if (typeof group === 'string') { encodeUuidTo(payload, 0, group); } else { payload.set(group, 0); } encodeStringTo(payload, 16, label, 32); encodeTimestampTo(view, 48, updatedAt); return payload; } function encodeEchoRequest(echoing) { const payload = new Uint8Array(64); payload.set(echoing); return payload; } function encodeSetWaveform(transient, hue, saturation, brightness, kelvin, period, cycles, skewRatio, waveform) { const payload = new Uint8Array(21); const view = new DataView(payload.buffer); payload[1] = transient ? 1 : 0; view.setUint16(2, hue, true); view.setUint16(4, saturation, true); view.setUint16(6, brightness, true); view.setUint16(8, kelvin, true); view.setUint32(10, period, true); view.setFloat32(14, cycles, true); view.setInt16(18, skewRatio, true); view.setUint8(20, waveform); return payload; } function encodeSetLightPower(level, duration) { const payload = new Uint8Array(6); const view = new DataView(payload.buffer); const value = typeof level === 'number' ? level : level ? 65535 : 0; view.setUint16(0, value, true); view.setUint32(2, duration, true); return payload; } function encodeSetWaveformOptional(transient, hue, saturation, brightness, kelvin, period, cycles, skewRatio, waveform, setHue, setSaturation, setBrightness, setKelvin) { const payload = new Uint8Array(25); const view = new DataView(payload.buffer); payload[1] = transient ? 1 : 0; view.setUint16(2, hue, true); view.setUint16(4, saturation, true); view.setUint16(6, brightness, true); view.setUint16(8, kelvin, true); view.setUint32(10, period, true); view.setFloat32(14, cycles, true); view.setInt16(18, skewRatio, true); view.setUint8(20, waveform); payload[21] = setHue ? 1 : 0; payload[22] = setSaturation ? 1 : 0; payload[23] = setBrightness ? 1 : 0; payload[24] = setKelvin ? 1 : 0; return payload; } function encodeSetInfrared(brightness) { const payload = new Uint8Array(2); const view = new DataView(payload.buffer); view.setUint16(0, brightness, true); return payload; } function encodeSetHevCycle(enable, durationSeconds) { const payload = new Uint8Array(5); const view = new DataView(payload.buffer); view.setUint8(0, enable ? 1 : 0); view.setUint32(1, durationSeconds, true); return payload; } function encodeSetHevCycleConfiguration(indication, durationSeconds) { const payload = new Uint8Array(5); const view = new DataView(payload.buffer); view.setUint8(0, indication ? 1 : 0); view.setUint32(1, durationSeconds, true); return payload; } function encodeGetRPower(relayIndex) { const payload = new Uint8Array(1); const view = new DataView(payload.buffer); view.setUint8(0, relayIndex); return payload; } function encodeSetRPower(relayIndex, level) { const payload = new Uint8Array(3); const view = new DataView(payload.buffer); view.setUint8(0, relayIndex); view.setUint16(1, level, true); return payload; } function encodeGet64(tileIndex, length, x, y, width) { const payload = new Uint8Array(6); const view = new DataView(payload.buffer); view.setUint8(0, tileIndex); view.setUint8(1, length); view.setUint8(2, 0); // reserved view.setUint8(3, x); view.setUint8(4, y); view.setUint8(5, width); return payload; } function encodeGetColorZones(startIndex, endIndex) { const payload = new Uint8Array(2); const view = new DataView(payload.buffer); view.setUint8(0, startIndex); view.setUint8(1, endIndex); return payload; } function encodeSetColorZones(startIndex, endIndex, hue, saturation, brightness, kelvin, duration, apply) { const payload = new Uint8Array(15); const view = new DataView(payload.buffer); view.setUint8(0, startIndex); view.setUint8(1, endIndex); view.setUint16(2, hue, true); view.setUint16(4, saturation, true); view.setUint16(6, brightness, true); view.setUint16(8, kelvin, true); view.setUint32(10, duration, true); view.setUint8(14, apply); return payload; } function encodeSetMultiZoneEffect(instanceid, effectType, speed, duration, parameters) { const payload = new Uint8Array(59); const view = new DataView(payload.buffer); view.setUint32(0, instanceid, true); view.setUint8(4, effectType); view.setUint8(5, 0); // reserved view.setUint8(6, 0); // reserved view.setUint32(7, speed, true); view.setBigUint64(11, duration, true); view.setUint32(19, 0); // reserved view.setUint32(23, 0); // reserved payload.set(parameters.slice(0, 32), 27); return payload; } function encodeSetExtendedColorZones(duration, apply, zoneIndex, colorsCount, colors) { const payload = new Uint8Array(664); const view = new DataView(payload.buffer); view.setUint32(0, duration, true); view.setUint8(4, apply); view.setUint16(5, zoneIndex, true); view.setUint8(7, colorsCount); for (let i = 0; i < 82; i++) { const color = colors[i] || { hue: 0, saturation: 0, brightness: 0, kelvin: 0 }; const offset = 8 + (i * 8); view.setUint16(offset, color.hue, true); view.setUint16(offset + 2, color.saturation, true); view.setUint16(offset + 4, color.brightness, true); view.setUint16(offset + 6, color.kelvin, true); } return payload; } function encodeSetUserPosition(tileIndex, userX, userY) { const payload = new Uint8Array(11); const view = new DataView(payload.buffer); view.setUint8(0, tileIndex); view.setUint8(1, 0); // reserved view.setUint8(2, 0); // reserved view.setFloat32(3, userX, true); view.setFloat32(7, userY, true); return payload; } function encodeSet64(tileIndex, length, x, y, width, duration, colors) { const payload = new Uint8Array(522); const view = new DataView(payload.buffer); view.setUint8(0, tileIndex); view.setUint8(1, length); view.setUint8(2, 0); // reserved view.setUint8(3, x); view.setUint8(4, y); view.setUint8(5, width); view.setUint32(6, duration, true); for (let i = 0; i < 64; i++) { const color = colors[i] || { hue: 0, saturation: 0, brightness: 0, kelvin: 0 }; const offset = 10 + (i * 8); view.setUint16(offset, color.hue, true); view.setUint16(offset + 2, color.saturation, true); view.setUint16(offset + 4, color.brightness, true); view.setUint16(offset + 6, color.kelvin, true); } return payload; } function encodeGetTileEffect() { const payload = new Uint8Array(2); payload[0] = 0; // reserved6 payload[1] = 0; // reserved7 return payload; } function encodeSetTileEffect(instanceid, effectType, speed, duration, skyType, cloudSaturationMin, paletteCount, palette) { const payload = new Uint8Array(188); const view = new DataView(payload.buffer); view.setUint8(0, 0); // reserved0 view.setUint8(1, 0); // reserved1 view.setUint32(2, instanceid, true); view.setUint8(6, effectType); view.setUint32(7, speed, true); view.setBigUint64(11, duration, true); view.setUint32(19, 0); // reserved2 view.setUint32(23, 0); // reserved3 view.setUint8(27, skyType); view.setUint8(28, 0); // reserved4[0] view.setUint8(29, 0); // reserved4[1] view.setUint8(30, 0); // reserved4[2] view.setUint8(31, cloudSaturationMin); view.setUint32(32, 0); // reserved5 (first 3 bytes) view.setUint32(35, 0); // reserved6 (24 bytes, filling with zeros) view.setUint32(51, 0); view.setUint32(55, 0); view.setUint8(59, paletteCount); for (let i = 0; i < 16; i++) { const color = palette[i] || { hue: 0, saturation: 0, brightness: 0, kelvin: 0 }; const offset = 60 + (i * 8); view.setUint16(offset, color.hue, true); view.setUint16(offset + 2, color.saturation, true); view.setUint16(offset + 4, color.brightness, true); view.setUint16(offset + 6, color.kelvin, true); } return payload; } function decodeLightState(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const reserved2 = decodeBytes(bytes, offsetRef, 2); const power = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const label = decodeString(bytes, offsetRef, 32); const reserved8 = decodeBytes(bytes, offsetRef, 8); return { hue, saturation, brightness, kelvin, power, label, reserved2, reserved8, }; } function decodeStateLightPower(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const level = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return level; } function decodeStateInfrared(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return brightness; } function decodeStateHevCycle(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const duration_s = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const remaining_s = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const last_power = !!view.getUint8(offsetRef.current); offsetRef.current += 1; return { duration_s, remaining_s, last_power, }; } function decodeStateHevCycleConfiguration(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const indication = view.getUint8(offsetRef.current); offsetRef.current += 1; const duration_s = view.getUint32(offsetRef.current, true); offsetRef.current += 4; return { indication, duration_s, }; } function decodeStateLastHevCycleResult(bytes, offsetRef) { const result = bytes[offsetRef.current]; offsetRef.current += 1; return result; } function decodeStateRPower(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const relay_index = view.getUint8(offsetRef.current); offsetRef.current += 1; const level = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return { relay_index, level, }; } function decodeStateDeviceChain(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const start_index = view.getUint8(offsetRef.current); offsetRef.current += 1; const devices = []; for (let i = 0; i < 16; i++) { const accel_meas_x = view.getInt16(offsetRef.current, true); offsetRef.current += 2; const accel_meas_y = view.getInt16(offsetRef.current, true); offsetRef.current += 2; const accel_meas_z = view.getInt16(offsetRef.current, true); offsetRef.current += 2; const reserved6 = decodeBytes(bytes, offsetRef, 2); const user_x = view.getFloat32(offsetRef.current, true); offsetRef.current += 4; const user_y = view.getFloat32(offsetRef.current, true); offsetRef.current += 4; const width = view.getUint8(offsetRef.current); offsetRef.current += 1; const height = view.getUint8(offsetRef.current); offsetRef.current += 1; const reserved7 = decodeBytes(bytes, offsetRef, 1); const device_version_vendor = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const device_version_product = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const reserved8 = decodeBytes(bytes, offsetRef, 4); const firmware_build = decodeTimestamp(bytes, offsetRef); const reserved9 = decodeBytes(bytes, offsetRef, 8); const firmware_version_minor = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const firmware_version_major = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const reserved10 = decodeBytes(bytes, offsetRef, 4); devices.push({ accel_meas_x, accel_meas_y, accel_meas_z, reserved6, user_x, user_y, width, height, reserved7, device_version_vendor, device_version_product, reserved8, firmware_build, reserved9, firmware_version_minor, firmware_version_major, reserved10, }); } const tile_devices_count = view.getUint8(offsetRef.current); offsetRef.current += 1; return { start_index, devices, tile_devices_count, }; } function decodeState64(bytes, offsetRef) { const tile_index = bytes[offsetRef.current]; offsetRef.current += 1; const reserved6 = decodeBytes(bytes, offsetRef, 1); const x = bytes[offsetRef.current]; offsetRef.current += 1; const y = bytes[offsetRef.current]; offsetRef.current += 1; const width = bytes[offsetRef.current]; offsetRef.current += 1; const view = new DataView(bytes.buffer, bytes.byteOffset); const colors = []; for (let i = 0; i < 64; i++) { const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; colors.push({ hue, saturation, brightness, kelvin, }); } return { tile_index, reserved6, x, y, width, colors, }; } function decodeStateZone(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const zones_count = view.getUint8(offsetRef.current); offsetRef.current += 1; const zone_index = view.getUint8(offsetRef.current); offsetRef.current += 1; const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; return { zones_count, zone_index, hue, saturation, brightness, kelvin, }; } function decodeStateMultiZone(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const zones_count = view.getUint8(offsetRef.current); offsetRef.current += 1; const zone_index = view.getUint8(offsetRef.current); offsetRef.current += 1; const colors = []; for (let i = 0; i < 8; i++) { const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; colors.push({ hue, saturation, brightness, kelvin }); } return { zones_count, zone_index, colors, }; } function decodeStateMultiZoneEffect(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const instanceid = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const type = view.getUint8(offsetRef.current); offsetRef.current += 1; const reserved6 = decodeBytes(bytes, offsetRef, 2); const speed = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const duration = view.getBigUint64(offsetRef.current, true); offsetRef.current += 8; const reserved7 = decodeBytes(bytes, offsetRef, 4); const reserved8 = decodeBytes(bytes, offsetRef, 4); const parameters = decodeBytes(bytes, offsetRef, 32); return { instanceid, type, reserved6, speed, duration, reserved7, reserved8, parameters, }; } function decodeStateExtendedColorZones(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const zones_count = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const zone_index = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const colors_count = view.getUint8(offsetRef.current); offsetRef.current += 1; const colors = []; for (let i = 0; i < 82; i++) { const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; colors.push({ hue, saturation, brightness, kelvin }); } return { zones_count, zone_index, colors_count, colors, }; } function decodeStateTileEffect(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const reserved0 = view.getUint8(offsetRef.current); offsetRef.current += 1; const instanceid = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const type = view.getUint8(offsetRef.current); offsetRef.current += 1; const speed = view.getUint32(offsetRef.current, true); offsetRef.current += 4; const duration = view.getBigUint64(offsetRef.current, true); offsetRef.current += 8; const reserved1 = decodeBytes(bytes, offsetRef, 4); const reserved2 = decodeBytes(bytes, offsetRef, 4); const skyType = view.getUint8(offsetRef.current); offsetRef.current += 1; const reserved3 = decodeBytes(bytes, offsetRef, 3); const cloudSaturationMin = view.getUint8(offsetRef.current); offsetRef.current += 1; const reserved4 = decodeBytes(bytes, offsetRef, 3); const cloudSaturationMax = view.getUint8(offsetRef.current); offsetRef.current += 1; const reserved5 = decodeBytes(bytes, offsetRef, 23); const palette_count = view.getUint8(offsetRef.current); offsetRef.current += 1; const palette = []; for (let i = 0; i < 16; i++) { const hue = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const saturation = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const brightness = view.getUint16(offsetRef.current, true); offsetRef.current += 2; const kelvin = view.getUint16(offsetRef.current, true); offsetRef.current += 2; palette.push({ hue, saturation, brightness, kelvin }); } return { reserved0, instanceid, type, speed, duration, reserved1, reserved2, skyType, reserved3, cloudSaturationMin, reserved4, cloudSaturationMax, reserved5, palette_count, palette, }; } function decodeSensorStateAmbientLight(bytes, offsetRef) { const view = new DataView(bytes.buffer, bytes.byteOffset); const lux = view.getFloat32(offsetRef.current, true); offsetRef.current += 4; return { lux, }; } const getHeaderSize = (view, offset = 0) => view.getUint16(offset, true); exports.getHeaderSize = getHeaderSize; const getHeaderFlags = (view, offset = 0) => view.getUint16(offset + 2, true); exports.getHeaderFlags = getHeaderFlags; const getHeaderTagged = (view, offset = 0) => !!(((0, exports.getHeaderFlags)(view, offset) >> 12) & 0b1); exports.getHeaderTagged = getHeaderTagged; const getHeaderSource = (view, offset = 0) => view.getUint32(offset + 4, true); exports.getHeaderSource = getHeaderSource; const getHeaderTarget = (bytes, offset = 0) => bytes.subarray(offset + 8, offset + 14); exports.getHeaderTarget = getHeaderTarget; const getHeaderResponseFlags = (view, offset = 0) => view.getUint8(offset + 22); exports.getHeaderResponseFlags = getHeaderResponseFlags; const getHeaderResponseRequired = (responseFlags) => (responseFlags & 0b1) > 0; exports.getHeaderResponseRequired = getHeaderResponseRequired; const getHeaderAcknowledgeRequired = (responseFlags) => (responseFlags & 0b10) > 0; exports.getHeaderAcknowledgeRequired = getHeaderAcknowledgeRequired; const getHeaderType = (view, offset = 0) => view.getUint16(offset + 32, true); exports.getHeaderType = getHeaderType; const getHeaderSequence = (view, offset = 0) => view.getUint8(offset + 23); exports.getHeaderSequence = getHeaderSequence; const getPayload = (bytes, offset = 0) => bytes.subarray(offset + 36); exports.getPayload = getPayload; function decodeHeader(bytes, offset = 0) { const view = new DataView(bytes.buffer, bytes.byteOffset); /** Frame Header */ const size = (0, exports.getHeaderSize)(view, offset); const flags = (0, exports.getHeaderFlags)(view, offset); const protocol = flags & 0xFFF; const addressable = !!((flags >> 12) & 0b1); const tagged = !!((flags >> 13) & 0b1); const origin = (flags >> 14) & 0b11; const source = (0, exports.getHeaderSource)(view, offset); /** Frame Address */ const target = (0, exports.getHeaderTarget)(bytes, offset); // last 2 bytes of target are reserved const reserved1 = () => bytes.subarray(offset + 14, offset + 16); const reserved2 = () => bytes.subarray(offset + 16, offset + 22); const responseFlags = (0, exports.getHeaderResponseFlags)(view, offset); const res_required = (0, exports.getHeaderResponseRequired)(responseFlags); const ack_required = (0, exports.getHeaderAcknowledgeRequired)(responseFlags); const reserved3 = (responseFlags & 0b11111100) >> 2; const sequence = (0, exports.getHeaderSequence)(view, offset); /** Protocol Header */ const reserved4 = () => bytes.subarray(offset + 24, offset + 32); const type = (0, exports.getHeaderType)(view, offset); const reserved5 = () => bytes.subarray(offset + 34, offset + 36); return { size, protocol, addressable, tagged, origin, source, target, reserved1, reserved2, res_required, ack_required, reserved3, reserved4, sequence, reserved5, type, }; } //# sourceMappingURL=encoding.js.map