UNPKG

@andrei-tatar/node-red-contrib-nibetcp

Version:

Node-red integration for Nibe S series heatpumps using modbus over TCP

85 lines (84 loc) 4.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const __1 = require(".."); const log_1 = require("../log"); module.exports = function (RED) { RED.nodes.registerType("nibe-register", function (config) { RED.nodes.createNode(this, config); const nibeConfig = RED.nodes.getNode(config.nibe); if (!(nibeConfig === null || nibeConfig === void 0 ? void 0 : nibeConfig.nibe$)) { return; } const log = log_1.logger === null || log_1.logger === void 0 ? void 0 : log_1.logger.scope(`reg-${config.id}`); const forceWrite = !!config.force; let timeoutMsec = (+config.timeout || 3) * 1000; const intervalMsec = (+config.interval || 10) * 1000; const forceRead$ = new rxjs_1.Subject(); const close$ = new rxjs_1.Subject(); const write$ = new rxjs_1.ReplaySubject(1); let consecutiveErrors = 0; const resetConnectionOnConsecutiveErrors = () => { if (++consecutiveErrors >= 3) { log === null || log === void 0 ? void 0 : log.trace("3 consecutive errors, reseting config"); nibeConfig.reset(); } }; (0, rxjs_1.concat)((0, rxjs_1.defer)(() => { consecutiveErrors = 0; log === null || log === void 0 ? void 0 : log.trace("starting subscription"); this.status({ fill: "yellow", text: "standby" }); return rxjs_1.EMPTY; }), (0, rxjs_1.combineLatest)([ nibeConfig.nibe$, (0, rxjs_1.merge)((0, rxjs_1.interval)(intervalMsec).pipe((0, operators_1.startWith)(0)), forceRead$), ])) .pipe((0, operators_1.concatMap)(([n]) => { log === null || log === void 0 ? void 0 : log.trace("reading register"); return n.readRegister(config.register, timeoutMsec).pipe((0, operators_1.catchError)((err) => { log === null || log === void 0 ? void 0 : log.trace("error reading"); this.warn(`Error reading ${config.register}: ${err}`); this.status({ fill: "red", text: `${err}` }); resetConnectionOnConsecutiveErrors(); return rxjs_1.EMPTY; })); }), (0, operators_1.tap)((v) => { log === null || log === void 0 ? void 0 : log.trace("got response", { value: v.formatted }); this.status({ fill: "blue", text: v.formatted }); consecutiveErrors = 0; }), (0, operators_1.finalize)(() => { log === null || log === void 0 ? void 0 : log.trace("disconnected"); this.status({ fill: "red", text: "disconnected" }); }), (0, operators_1.retry)({ delay: 20000 }), (0, operators_1.takeUntil)(close$)) .subscribe({ next: (value) => this.send({ payload: value, topic: config.topic }), complete: () => log === null || log === void 0 ? void 0 : log.trace("complete!"), }); write$ .pipe((0, operators_1.filter)(__1.isDefined), (0, operators_1.withLatestFrom)(nibeConfig.nibe$), (0, operators_1.concatMap)(([value, nibeConnection]) => nibeConnection .writeRegister(config.register, value, forceWrite, timeoutMsec) .pipe((0, operators_1.tap)({ error: (err) => { this.warn(`Error writing ${value} to ${config.register}: ${err}`); this.status({ fill: "red", text: `${err}` }); resetConnectionOnConsecutiveErrors(); }, complete: () => { write$.next(null); forceRead$.next(); consecutiveErrors = 0; }, }), (0, operators_1.takeUntil)(close$))), (0, operators_1.retry)({ delay: 10000 })) .subscribe(); this.on("input", (msg, _, done) => { if (config.filter && config.topic && msg.topic !== config.topic) { done === null || done === void 0 ? void 0 : done(); return; } write$.next(+msg.payload); done === null || done === void 0 ? void 0 : done(); }); this.on("close", () => close$.next()); }); };