UNPKG

@gravypower/node-red-franklinwh

Version:

Node-RED node to control FranklinWH gateway

102 lines (87 loc) 3.94 kB
const franklinwh = require('franklinwh'); module.exports = function(RED) { function FranklinWHConfigNode(config) { RED.nodes.createNode(this, config); const node = this; // Unified properties for config fields this.host = config.host || ""; this.serialNumber = config.serialNumber || ""; this.username = this.credentials?.username; this.password = this.credentials?.password; // migrate/compatibility: keep gateway as either host or serialNumber (old flows may expect gateway) this.gateway = this.serialNumber || config.gateway || this.host; // Debug logging to aid diagnosing node registration node.debug(`FranklinWHConfigNode initialized. host: ${this.host}, serialNumber: ${this.serialNumber}, username: ${this.username ? '[set]' : '[not set]'}, password: ${this.password ? '[set]' : '[not set]'}`); // Check if we have all required fields if (!this.host || !this.serialNumber || !this.username || !this.password) { node.error("Missing configuration: host, serialNumber, username and password are all required."); return; } this.api = null; this.connecting = null; // Track ongoing connection attempts this.lastConnectionError = null; // Initialize connection with proper Promise handling const connect = async (force = false) => { if (this.api && !force) { return this.api; } // If there's already a connection attempt in progress, wait for it if (this.connecting) { return this.connecting; } // Start new connection attempt this.connecting = (async () => { try { node.debug("Initiating connection to FranklinWH gateway..."); // franklinwh(username, password, gateway, base) this.api = await franklinwh( this.username, this.password, this.serialNumber || this.gateway, this.host ); node.log("Successfully connected to FranklinWH gateway"); this.lastConnectionError = null; return this.api; } catch (error) { this.api = null; this.lastConnectionError = error; node.error("Connection failed: " + error.message); throw error; } finally { this.connecting = null; } })(); return this.connecting; }; // Initial connection attempt connect().catch(() => { // Errors are already logged in connect() node.status({fill: "red", shape: "ring", text: "Connection failed"}); }); this.getApi = async function(needsNewAuth = false) { try { // If we need new auth or last attempt failed, force new connection const forceNewConnection = needsNewAuth || this.lastConnectionError; return await connect(forceNewConnection); } catch (error) { const errorMsg = needsNewAuth ? "Failed to refresh connection: " : "Failed to connect: "; throw new Error(errorMsg + error.message); } }; node.on('close', function(done) { node.api = null; node.connecting = null; node.lastConnectionError = null; done(); }); } RED.nodes.registerType("franklinwh-config", FranklinWHConfigNode, { credentials: { username: {type: "text", required: true}, password: {type: "password", required: true} } }); }