zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
97 lines • 4.64 kB
JavaScript
;
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