lifxlan
Version:
TypeScript library for controlling LIFX products over LAN
937 lines • 35.2 kB
JavaScript
"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);
}
}
// Reuse TextEncoder instance for performance - avoid repeated allocations
const textEncoder = new TextEncoder();
function encodeStringTo(bytes, offset, value, byteLength) {
textEncoder.encodeInto(value, bytes.subarray(offset));
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) {
const foundIndex = bytes
.subarray(offsetRef.current, offsetRef.current + maxLength)
.findIndex((value) => value === 0);
const length = foundIndex >= 0 ? foundIndex : maxLength;
const value = textDecoder.decode(bytes.subarray(offsetRef.current, offsetRef.current + length));
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 {
bytes: bytes.subarray(0, 36),
size,
protocol,
addressable,
tagged,
origin,
source,
target,
reserved1,
reserved2,
res_required,
ack_required,
reserved3,
reserved4,
sequence,
reserved5,
type,
};
}
//# sourceMappingURL=encoding.js.map