node-red-contrib-hubitat
Version:
Node Red module for Hubitat API
137 lines (123 loc) • 4.36 kB
JavaScript
module.exports = function HubitatModeModule(RED) {
function HubitatModeNode(config) {
RED.nodes.createNode(this, config);
this.hubitat = RED.nodes.getNode(config.server);
this.name = config.name;
this.sendEvent = config.sendEvent;
this.currentMode = undefined;
this.shape = this.sendEvent ? 'dot' : 'ring';
this.currentStatusText = '';
this.currentStatusFill = undefined;
const node = this;
if (!node.hubitat) {
node.error('Hubitat server not configured');
return;
}
this.updateStatus = (fill = null, text = null) => {
const status = { fill, shape: this.shape, text };
node.currentStatusText = text;
node.currentStatusFill = fill;
if (fill === null) {
delete status.shape;
delete status.fill;
}
if (text === null) {
delete status.text;
}
if (node.hubitat.useWebsocket) {
if (fill === null) {
status.fill = 'green';
status.shape = this.shape;
} else if (fill === 'blue') {
status.fill = 'green';
}
if (!node.hubitat.wsStatusOk) {
status.fill = 'red';
status.text = 'WS ERROR';
}
}
node.status(status);
};
async function initializeMode() {
return node.hubitat.getMode().then((mode) => {
if (!mode) { throw new Error(JSON.stringify(mode)); }
node.currentMode = mode.filter((eachMode) => eachMode.active)[0].name;
node.log(`Initialized. mode: ${node.currentMode}`);
node.updateStatus('blue', node.currentMode);
}).catch((err) => {
node.warn(`Unable to initialize mode: ${err.message}`);
node.updateStatus('red', 'Uninitialized');
throw err;
});
}
const eventCallback = async (event) => {
node.debug(`Event received: ${JSON.stringify(event)}`);
node.currentMode = event.value;
node.debug(`Mode: ${node.currentMode}`);
if (node.sendEvent) {
const msg = {
payload: {
name: 'mode',
value: node.currentMode,
displayName: event.displayName,
descriptionText: event.descriptionText,
},
topic: 'hubitat-mode',
};
node.send(msg);
}
node.updateStatus('blue', node.currentMode);
};
this.hubitat.hubitatEvent.on('mode', eventCallback);
const systemStartCallback = async () => {
const previousMode = node.currentMode;
try {
await initializeMode();
} catch (err) {
return;
}
if (node.currentMode !== previousMode) {
node.log(`Fix desynchronization: "${previousMode}" --> "${node.currentMode}"`);
const event = { value: node.currentMode, descriptionText: 'Event triggered by systemStart and generated by Node-RED' };
eventCallback(event);
}
};
this.hubitat.hubitatEvent.on('systemStart', systemStartCallback);
const wsOpened = async () => {
node.updateStatus(node.currentStatusFill, node.currentStatusText);
};
this.hubitat.hubitatEvent.on('websocket-opened', wsOpened);
const wsClosed = async () => {
node.updateStatus(node.currentStatusFill, node.currentStatusText);
};
this.hubitat.hubitatEvent.on('websocket-closed', wsClosed);
this.hubitat.hubitatEvent.on('websocket-error', wsClosed);
initializeMode().catch(() => {});
node.on('input', async (msg, send, done) => {
node.debug('Input received');
if (node.currentMode === undefined) {
try {
await initializeMode();
} catch (err) {
return;
}
}
const output = {
...msg,
payload: { name: 'mode', value: node.currentMode },
topic: 'hubitat-mode',
};
send(output);
done();
});
node.on('close', () => {
node.debug('Closed');
this.hubitat.hubitatEvent.removeListener('mode', eventCallback);
this.hubitat.hubitatEvent.removeListener('systemStart', systemStartCallback);
this.hubitat.hubitatEvent.removeListener('websocket-opened', wsOpened);
this.hubitat.hubitatEvent.removeListener('websocket-closed', wsClosed);
this.hubitat.hubitatEvent.removeListener('websocket-error', wsClosed);
});
}
RED.nodes.registerType('hubitat mode', HubitatModeNode);
};