UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

97 lines 4.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseSWVZFRawZclCommand = exports.shiftUtcSecondsByOffsetMonths = exports.formatUtcSecondsToIsoWithOffset = exports.getRuntimeLocalOffsetSeconds = exports.parseIsoWithOffsetToUtcSeconds = exports.deviceLocal2000ToUTCSeconds = exports.utcToDeviceLocal2000Seconds = exports.YEAR_2000_IN_UTC = void 0; /** * Unix timestamp in seconds for `2000-01-01T00:00:00Z`. * Sonoff irrigation devices encode local datetimes relative to this base. */ exports.YEAR_2000_IN_UTC = Math.floor(Date.UTC(2000, 0, 1) / 1000); /** * Convert Unix UTC seconds to device local-time seconds (2000 base). */ const utcToDeviceLocal2000Seconds = (utcSeconds, offsetSeconds) => { return utcSeconds + offsetSeconds - exports.YEAR_2000_IN_UTC; }; exports.utcToDeviceLocal2000Seconds = utcToDeviceLocal2000Seconds; /** * Convert device local-time seconds (2000 base) back to Unix UTC seconds. */ const deviceLocal2000ToUTCSeconds = (deviceSeconds, offsetSeconds) => { return deviceSeconds - offsetSeconds + exports.YEAR_2000_IN_UTC; }; exports.deviceLocal2000ToUTCSeconds = deviceLocal2000ToUTCSeconds; /** * Parse ISO 8601 datetime (must include `Z` or `±HH:mm`) to Unix UTC seconds. * Returns `undefined` when format is invalid or parsed value is negative. */ const parseIsoWithOffsetToUtcSeconds = (value) => { if (!/(Z|[+-]\d{2}:\d{2})$/.test(value)) { return; } const timeMs = new Date(value).getTime(); if (Number.isNaN(timeMs)) { return; } const seconds = Math.floor(timeMs / 1000); if (seconds < 0) { return; } return seconds; }; exports.parseIsoWithOffsetToUtcSeconds = parseIsoWithOffsetToUtcSeconds; /** * Get runtime local timezone offset in seconds for the specified UTC timestamp. */ const getRuntimeLocalOffsetSeconds = (utcSeconds) => { const date = new Date(utcSeconds * 1000); return -date.getTimezoneOffset() * 60; }; exports.getRuntimeLocalOffsetSeconds = getRuntimeLocalOffsetSeconds; /** * Format Unix UTC seconds to ISO 8601 with the specified timezone offset. * Falls back to the runtime local timezone offset when not provided. */ const formatUtcSecondsToIsoWithOffset = (utcSeconds, offsetSeconds) => { const resolvedOffsetSeconds = typeof offsetSeconds === "number" && Number.isFinite(offsetSeconds) ? offsetSeconds : (0, exports.getRuntimeLocalOffsetSeconds)(utcSeconds); const sign = resolvedOffsetSeconds >= 0 ? "+" : "-"; const offsetMinutesAbs = Math.abs(Math.floor(resolvedOffsetSeconds / 60)); const offsetHours = Math.floor(offsetMinutesAbs / 60); const offsetMinutes = offsetMinutesAbs % 60; const localMs = utcSeconds * 1000 + resolvedOffsetSeconds * 1000; const localDate = new Date(localMs); return (`${localDate.getUTCFullYear()}-${String(localDate.getUTCMonth() + 1).padStart(2, "0")}-${String(localDate.getUTCDate()).padStart(2, "0")}T` + `${String(localDate.getUTCHours()).padStart(2, "0")}:${String(localDate.getUTCMinutes()).padStart(2, "0")}:${String(localDate.getUTCSeconds()).padStart(2, "0")}` + `${sign}${String(offsetHours).padStart(2, "0")}:${String(offsetMinutes).padStart(2, "0")}`); }; exports.formatUtcSecondsToIsoWithOffset = formatUtcSecondsToIsoWithOffset; /** * Shift UTC seconds by local calendar months under a fixed UTC -> local offset. */ const shiftUtcSecondsByOffsetMonths = (utcSeconds, monthDelta, offsetSeconds = 0) => { const localMs = utcSeconds * 1000 + offsetSeconds * 1000; const localDate = new Date(localMs); const shiftedLocalMs = Date.UTC(localDate.getUTCFullYear(), localDate.getUTCMonth() + monthDelta, localDate.getUTCDate(), localDate.getUTCHours(), localDate.getUTCMinutes(), localDate.getUTCSeconds(), localDate.getUTCMilliseconds()); return Math.floor((shiftedLocalMs - offsetSeconds * 1000) / 1000); }; exports.shiftUtcSecondsByOffsetMonths = shiftUtcSecondsByOffsetMonths; /** * Extract the ZCL command id and payload from a raw SWV-ZN/ZF frame. * Handles both standard and manufacturer-specific headers. */ const parseSWVZFRawZclCommand = (buffer) => { if (buffer.length < 3) { return; } const frameControl = buffer[0]; const hasManufacturerCode = (frameControl & 0b100) !== 0; const zclHeaderLength = hasManufacturerCode ? 5 : 3; if (buffer.length < zclHeaderLength) { return; } return { commandId: buffer[zclHeaderLength - 1], payload: buffer.subarray(zclHeaderLength), }; }; exports.parseSWVZFRawZclCommand = parseSWVZFRawZclCommand; //# sourceMappingURL=sonoff.js.map