UNPKG

homebridge-virtual-accessories

Version:
102 lines 5.35 kB
import { Trigger } from './trigger.js'; import { Sensor } from '../sensor.js'; import { Utils } from '../../utils/utils.js'; import { Cron } from 'croner'; import { DateTimeFormatter, LocalDateTime, ZonedDateTime, ZoneId } from '@js-joda/core'; import '@js-joda/timezone'; /** * CronTrigger - Trigger implementation */ export class CronTrigger extends Trigger { cronJob; constructor(sensor, name) { super(sensor, name); const triggerConfig = this.sensorConfig.cronTrigger; if (triggerConfig.isDisabled) { this.log.info(`[${this.sensorConfig.accessoryName}] Cron trigger is disabled`); return; } if (triggerConfig.disableTriggerEventLogging) { this.log.info(`[${this.sensorConfig.accessoryName}] Cron trigger event logging is disabled. Sensor state changes will not be displayed in the logs`); } // Hardcode reset delay const resetDelayMillis = 3 * 1000; // 3 second reset delay // System settings - date/time formatting - timezone const timezone = (triggerConfig.zoneId !== undefined) ? triggerConfig.zoneId : Intl.DateTimeFormat().resolvedOptions().timeZone; this.log.debug(`[${this.sensorConfig.accessoryName}] Setting timezone to '${timezone}'`); const zoneId = ZoneId.of(timezone); this.log.debug(`[${this.sensorConfig.accessoryName}] Setting ZoneId to '${zoneId}'`); const cronStart = this.getZonedDateTime(triggerConfig.startDateTime, zoneId); const cronEnd = this.getZonedDateTime(triggerConfig.endDateTime, zoneId); this.log.debug(`[${this.sensorConfig.accessoryName}] Start time: '${cronStart?.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)}'`); this.log.debug(`[${this.sensorConfig.accessoryName}] End time: '${cronEnd?.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)}'`); this.log.debug(`[${this.sensorConfig.accessoryName}] Now time: '${Utils.now().format(DateTimeFormatter.ISO_ZONED_DATE_TIME)}'`); // If we're past the end date, don't even bother starting up the cron job if (cronEnd && Utils.now().isAfter(cronEnd)) { this.log.info(`[${this.sensorConfig.accessoryName}] After cron end: '${triggerConfig.endDateTime}'. Not setting up cron job`); return; // eslint-disable-next-line brace-style } else if (cronStart && (Utils.now().isEqual(cronStart) || Utils.now().isBefore(cronStart))) { this.log.info(`[${this.sensorConfig.accessoryName}] Before cron start: '${triggerConfig.startDateTime}'. Waiting for start time`); } let firstTrigger = true; this.cronJob = new Cron(triggerConfig.pattern, { name: `Schedule Cron Job (${this.sensorConfig.accessoryName})`, startAt: this.includeStartTime(triggerConfig.startDateTime), stopAt: this.includeEndTime(triggerConfig.endDateTime), timezone: timezone, }, (async () => { if (firstTrigger) { this.log.info(`[${this.sensorConfig.accessoryName}] Starting cron job`); firstTrigger = false; } this.log.debug(`[${this.sensorConfig.accessoryName}] Matched cron pattern '${triggerConfig.pattern}'. Triggering sensor`); sensor.triggerSensorState(Sensor.TRIGGERED, this, triggerConfig.disableTriggerEventLogging); await Utils.delay(resetDelayMillis); sensor.triggerSensorState(Sensor.NORMAL, this, triggerConfig.disableTriggerEventLogging); if (!this.cronJob.nextRun()) { this.log.info(`[${this.sensorConfig.accessoryName}] Stopping cron job`); } })); this.displayNextRun(this.cronJob); } /** * Private methods */ displayNextRun(cronJob) { let nextRunTimestamp = cronJob.nextRun()?.toISOString(); nextRunTimestamp = (nextRunTimestamp === undefined) ? 'None scheduled' : `${nextRunTimestamp.split('.')[0]} (count: ${cronJob.options.maxRuns})`; this.log.debug(`[${this.sensorConfig.accessoryName}] Next ${cronJob.name} run: ${nextRunTimestamp}`); } getZonedDateTime(datetime, zoneId) { if (datetime === undefined) { return undefined; } const localDateTimeLength = 'yyyy:MM:ddThh:mm:ss'.length; const localDatetime = datetime.substring(0, localDateTimeLength); const zonedDateTime = ZonedDateTime.of(LocalDateTime.parse(localDatetime), zoneId); return zonedDateTime; } // The cron implementation is exclusive of start and end times // To include start time, setting start time to one second earlier // To include end time, setting end time to one second later includeStartTime(startTime) { return this.adjustTime(startTime, -1); } includeEndTime(endTime) { return this.adjustTime(endTime, 1); } adjustTime(datetime, adjusmentSeconds) { if (datetime === undefined) { return undefined; } let localDateTime = LocalDateTime.parse(datetime); localDateTime = localDateTime.plusSeconds(adjusmentSeconds); return localDateTime.format(DateTimeFormatter.ISO_DATE_TIME); } } export const dynamicTrigger = CronTrigger; //# sourceMappingURL=triggerCron.js.map