node-red-contrib-home-assistant-websocket
Version:
Node-RED integration with Home Assistant through websocket and REST API
225 lines (224 loc) • 11.8 kB
JavaScript
"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;