UNPKG

node-red-contrib-home-assistant-websocket

Version:
225 lines (224 loc) 11.8 kB
"use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _TimeController_instances, _TimeController_cronjob, _TimeController_isProcessing, _TimeController_shouldRunAgain, _TimeController_createCronjob, _TimeController_destoryCronjob, _TimeController_checkValidDateString, _TimeController_formatDate, _TimeController_getEntity, _TimeController_getOffset, _TimeController_getRandomOffset, _TimeController_getDays, _TimeController_onTimer, _TimeController_processEvent; Object.defineProperty(exports, "__esModule", { value: true }); const cronosjs_1 = require("cronosjs"); const selectn_1 = __importDefault(require("selectn")); const ExposeAsMixin_1 = __importDefault(require("../../common/controllers/ExposeAsMixin")); const OutputController_1 = __importDefault(require("../../common/controllers/OutputController")); const ConfigError_1 = __importDefault(require("../../common/errors/ConfigError")); const const_1 = require("../../const"); const globals_1 = require("../../globals"); const date_1 = require("../../helpers/date"); const utils_1 = require("../../helpers/utils"); const DEFAULT_PROPERTY = 'state'; const ExposeAsController = (0, ExposeAsMixin_1.default)((OutputController_1.default)); class TimeController extends ExposeAsController { constructor() { super(...arguments); _TimeController_instances.add(this); _TimeController_cronjob.set(this, null); _TimeController_isProcessing.set(this, false); _TimeController_shouldRunAgain.set(this, false); } onClose() { __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_destoryCronjob).call(this); } handleEvent() { __classPrivateFieldSet(this, _TimeController_shouldRunAgain, true, "f"); __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_processEvent).call(this); } } _TimeController_cronjob = new WeakMap(), _TimeController_isProcessing = new WeakMap(), _TimeController_shouldRunAgain = new WeakMap(), _TimeController_instances = new WeakSet(), _TimeController_createCronjob = function _TimeController_createCronjob(crontab) { this.node.debug(`Creating cronjob: ${crontab}`); __classPrivateFieldSet(this, _TimeController_cronjob, (0, cronosjs_1.scheduleTask)(crontab, async () => { try { await __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_onTimer).call(this); } catch (e) { this.node.error(e); this.status.setError(); } }, {}), "f"); }, _TimeController_destoryCronjob = function _TimeController_destoryCronjob() { var _a; if (__classPrivateFieldGet(this, _TimeController_cronjob, "f") != null) { this.node.debug(`Destroying cronjob: ${(_a = __classPrivateFieldGet(this, _TimeController_cronjob, "f")) === null || _a === void 0 ? void 0 : _a.nextRun}`); __classPrivateFieldGet(this, _TimeController_cronjob, "f").stop(); __classPrivateFieldSet(this, _TimeController_cronjob, null, "f"); } }, _TimeController_checkValidDateString = function _TimeController_checkValidDateString(str) { if (str === undefined || str === 'unavailable' || (typeof str !== 'string' && typeof str !== 'number')) { throw new ConfigError_1.default(str === 'unavailable' ? 'ha-time.status.unavailable' : 'ha-time.status.invalid_property'); } }, _TimeController_formatDate = function _TimeController_formatDate(d) { return (0, date_1.formatDate)({ date: d, options: { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', }, }); }, _TimeController_getEntity = function _TimeController_getEntity() { return this.homeAssistant.websocket.getState(this.node.config.entityId); }, _TimeController_getOffset = async function _TimeController_getOffset() { let offset = this.node.config.offset || '0'; if (this.node.config.offsetType === const_1.TypedInputTypes.JSONata) { offset = await this.jsonataService.evaluate(offset); } const offsetMs = (0, utils_1.getTimeInMilliseconds)(Number(offset), this.node.config.offsetUnits); if (isNaN(offsetMs)) { throw new ConfigError_1.default(['ha-time.error.offset_nan', { offset }]); } return Number(offsetMs); }, _TimeController_getRandomOffset = function _TimeController_getRandomOffset(date, offset) { // if not repeating stay ahead of current time if (!this.node.config.repeatDaily && Math.sign(offset) === -1) { const cronTimestamp = date.getTime(); const maxOffset = Math.max(Date.now(), cronTimestamp + offset) - cronTimestamp; return maxOffset * Math.random(); } return offset * Math.random(); }, _TimeController_getDays = function _TimeController_getDays() { const days = { sunday: 0, monday: 1, tuesday: 2, wednesday: 3, thursday: 4, friday: 5, saturday: 6, }; const selectedDays = Object.keys(days).reduce((acc, day) => { if (this.node.config[day]) { acc.push(days[day]); } return acc; }, []); if (selectedDays.length === 0) { throw new ConfigError_1.default('ha-time.error.no_days_selected'); } return selectedDays.length === 7 ? '*' : selectedDays.join(','); }, _TimeController_onTimer = async function _TimeController_onTimer() { var _a; if (this.isEnabled === false) return; const now = new Date(); const entity = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_getEntity).call(this); const msg = {}; await this.setCustomOutputs(this.node.config.outputProperties, msg, { config: this.node.config, entity, entityState: entity === null || entity === void 0 ? void 0 : entity.state, triggerId: entity === null || entity === void 0 ? void 0 : entity.entity_id, }); if (this.node.config.repeatDaily) { const sentTime = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_formatDate).call(this, now); // convert luxon to date const nextTime = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_formatDate).call(this, (_a = __classPrivateFieldGet(this, _TimeController_cronjob, "f")) === null || _a === void 0 ? void 0 : _a.nextRun); this.status.setSuccess([ 'ha-time.status.sent_and_next', { sentTime, nextTime, }, ]); } else { this.status.setSuccess('ha-time.status.sent'); } this.node.send(msg); }, _TimeController_processEvent = async function _TimeController_processEvent() { var _a; if (__classPrivateFieldGet(this, _TimeController_isProcessing, "f")) return; __classPrivateFieldSet(this, _TimeController_isProcessing, true, "f"); try { do { __classPrivateFieldSet(this, _TimeController_shouldRunAgain, false, "f"); const property = this.node.config.property || DEFAULT_PROPERTY; const entity = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_getEntity).call(this); const dateString = (0, selectn_1.default)(property, entity); let date; let offset; __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_destoryCronjob).call(this); // Validate inputs __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_checkValidDateString).call(this, dateString); offset = await __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_getOffset).call(this); const digits = (0, utils_1.parseTime)(dateString); // Doesn't match time format 00:00:00 if (!digits) { if (!(0, utils_1.isValidDate)(dateString)) { throw new ConfigError_1.default([ 'ha-time.error.invalid_date', { date: dateString }, ], 'ha-time.status.invalid_date'); } date = new Date(dateString); } else { date = new Date(); date.setHours(digits.hour); date.setMinutes(digits.minutes); date.setSeconds(digits.seconds); } // plus minus offset if (offset !== 0) { if (this.node.config.randomOffset) { offset = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_getRandomOffset).call(this, date, offset); } const timestamp = date.getTime() + offset; date.setTime(timestamp); } let crontab = `${date.getSeconds()} ${date.getMinutes()} ${date.getHours()} ${date.getDate()} ${date.getMonth() + 1} *`; // Create repeating crontab string if (this.node.config.repeatDaily) { const days = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_getDays).call(this); crontab = `${date.getSeconds()} ${date.getMinutes()} ${date.getHours()} * * ${days}`; } else if (date.getTime() < Date.now()) { if (!this.node.config.ignorePastDate) { this.node.warn(globals_1.RED._('ha-time.error.in_the_past', { date: dateString, })); } this.status.setFailed('ha-time.status.in_the_past'); return; } __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_createCronjob).call(this, crontab); const nextTime = __classPrivateFieldGet(this, _TimeController_instances, "m", _TimeController_formatDate).call(this, (_a = __classPrivateFieldGet(this, _TimeController_cronjob, "f")) === null || _a === void 0 ? void 0 : _a.nextRun); this.status.setText(globals_1.RED._('ha-time.status.next_at', { nextTime })); } while (__classPrivateFieldGet(this, _TimeController_shouldRunAgain, "f")); } catch (e) { if (e instanceof Error) { this.node.error(e); this.status.setError(e.message); } } finally { __classPrivateFieldSet(this, _TimeController_isProcessing, false, "f"); } }; exports.default = TimeController;