@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
JavaScript
;
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());
});
};