homebridge-virtual-accessories
Version:
Virtual HomeKit accessories for Homebridge.
162 lines • 5.9 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Duration, Instant, ZonedDateTime, ZoneId } from '@js-joda/core';
import '@js-joda/timezone';
/**
* shutdownSignal
*/
export const shutdownSignal = {
isShuttingDown: false,
};
/**
* Utils
*/
export class Utils {
static base64DecodeToHexString(base64String) {
const hexString = Buffer.from(base64String, 'base64').toString('hex');
return hexString;
}
static hexStringEncodeToBase64(hexString) {
const base64String = Buffer.from(hexString, 'hex').toString('base64');
return base64String;
}
static concatenate(num1, num2) {
return (num1 * 100) + num2;
}
static now() {
const now = ZonedDateTime.ofInstant(Instant.now(), ZoneId.SYSTEM);
return now;
}
static zonedDateTime(datetime) {
const zonedDateTime = ZonedDateTime.parse(datetime);
return zonedDateTime;
}
static secondsToHHmmss(seconds) {
let secondsDuration = Math.max(seconds, 0);
const hours = Math.floor(secondsDuration / 3600);
secondsDuration = secondsDuration - (hours * 3600);
const mins = Math.floor(secondsDuration / 60);
secondsDuration = secondsDuration - (mins * 60);
const secs = secondsDuration;
let hhmmss = '';
if (hours > 0) {
hhmmss += hours.toString().padStart(2, '0') + 'h';
}
if (mins > 0 || hours > 0) {
hhmmss += mins.toString().padStart(2, '0') + 'm';
}
hhmmss += secs.toString().padStart(2, '0') + 's';
return hhmmss;
}
static daysHoursMinutesSecondsToSeconds(days, hours, minutes, seconds) {
if (days < 0 || hours < 0 || minutes < 0 || seconds < 0) {
return 0;
}
const convertedSeconds = (((days * 24) + hours) * 60 + minutes) * 60 + seconds;
return convertedSeconds;
}
static secondsToDaysHoursMinutesSeconds(seconds) {
if (seconds <= 0) {
return [0, 0, 0, 0];
}
const convertedDays = Math.trunc(((seconds / 60) / 60) / 24);
seconds = seconds - convertedDays * 24 * 60 * 60;
const convertedHours = Math.trunc((seconds / 60) / 60);
seconds = seconds - convertedHours * 60 * 60;
const convertedMinutes = Math.trunc((seconds / 60));
seconds = seconds - convertedMinutes * 60;
const convertedSeconds = seconds;
return [convertedDays, convertedHours, convertedMinutes, convertedSeconds];
}
static debounceMillis = 300;
static debounce(func, delayMillis = Utils.debounceMillis, accessoryName, log) {
if (delayMillis <= 0) {
log.error(`[${accessoryName}] Invalid delay: ${delayMillis}`);
return;
}
let timeoutId;
return function (...args) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const context = this;
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(context, args);
}, delayMillis)
.unref();
};
}
static async delay(millis, accessoryName, log) {
if (millis <= 0) {
log.error(`[${accessoryName}] Invalid delay: ${millis}`);
return;
}
return new Promise(resolve => setTimeout(resolve, millis)
.unref());
}
// serialise Map to JSON
static mapToJson(map) {
return JSON.stringify(Array.from(map.entries()));
}
// de-serialise JSON to Map
static jsonToMap(json) {
return new Map(JSON.parse(json));
}
/**
* Get the field name
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static proxiedPropertiesOf(obj) {
return new Proxy({}, {
get: (_, prop) => prop,
set: () => {
throw Error('Set not supported');
},
});
}
static required(field) {
return (field !== undefined);
}
static notEmpty(field) {
let notEmpty = false;
if (Utils.required(field)) {
notEmpty = Array.isArray(field) ? field.length > 0 : field !== '';
}
return notEmpty;
}
static isPercentage(value) {
return (value >= 0 && value <= 100);
}
static isDegrees(value) {
return (value >= 0 && value <= 360);
}
static isValidTransition(value) {
return (value >= 0);
}
static isValidTimeout(value) {
return (value >= 0);
}
static restoreRunningTimer(timer, cachedStartTime, cachedDuration, callback, accessoryName, log) {
if (cachedDuration < 0) {
log.error(`[${accessoryName}] Invalid cached duration: ${cachedDuration}`);
return;
}
const elapsedTime = Math.trunc(Duration.between(Utils.zonedDateTime(cachedStartTime), Utils.now()).toMillis() / 1000); // seconds
log.debug(`[${accessoryName}] Elapsed Time: ${elapsedTime}`);
if (elapsedTime < 0) {
log.error(`[${accessoryName}] Invalid elapsed time: ${elapsedTime}. Start time cannot be in the future`);
return;
}
let timeRemaining = (cachedDuration - elapsedTime);
log.debug(`[${accessoryName}] Time Remaining: ${timeRemaining}`);
// If the timer is expired, set timer to 1 second to issue trigger switch off
timeRemaining = (timeRemaining <= 0) ? 1 : timeRemaining;
if (timeRemaining === 1) {
log.debug(`[${accessoryName}] Timer expired. Setting timer to 1 second to trigger switch off`);
}
else {
log.debug(`[${accessoryName}] Setting Timer for remaining time of (${timeRemaining} seconds)`);
}
timer.stop();
timer.start(callback, timeRemaining);
}
}
//# sourceMappingURL=utils.js.map