{"size": 4847, "ext": "js", "max_stars_repo_path": "nodes/hsm.js", "max_stars_repo_name": "Botched1/node-red-contrib-hubitat", "max_stars_repo_stars_event_min_datetime": "2020-02-28T01:27:05.000Z", "max_stars_repo_stars_event_max_datetime": "2022-02-02T18:56:16.000Z", "max_issues_repo_path": "nodes/hsm.js", "max_issues_repo_name": "fblackburn1/node-red-contrib-hubitat", "max_issues_repo_issues_event_min_datetime": "2020-02-19T19:12:38.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-27T14:39:14.000Z", "max_forks_repo_path": "nodes/hsm.js", "max_forks_repo_name": "Botched1/node-red-contrib-hubitat", "max_forks_repo_forks_event_min_datetime": "2020-02-17T21:21:35.000Z", "max_forks_repo_forks_event_max_datetime": "2021-07-23T11:21:42.000Z"}
{"max_stars_count": 19, "max_issues_count": 70, "max_forks_count": 14, "avg_line_length": 31.474025974, "max_line_length": 98, "alphanum_fraction": 0.5782958531}
module.exports = function HubitatHsmModule(RED) {
  function HubitatHsmNode(config) {
    RED.nodes.createNode(this, config);

    this.hubitat = RED.nodes.getNode(config.server);
    this.name = config.name;
    this.sendEvent = config.sendEvent;
    this.currentHsm = undefined;
    this.shape = this.sendEvent ? 'dot' : 'ring';
    this.currentStatusText = '';
    this.currentStatusFill = undefined;
    this.alert = false;

    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 initializeHsm() {
      return node.hubitat.getHsm().then((hsm) => {
        if (!hsm) { throw new Error(JSON.stringify(hsm)); }
        node.currentHsm = hsm.hsm;
        node.log(`Initialized. HSM: ${node.currentHsm}`);
        node.updateStatus('blue', node.currentHsm);
      }).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)}`);
      if ((event.name === 'hsmAlert') && (['cancel', 'cancelRuleAlerts'].includes(event.value))) {
        node.alert = false;
      } else if (event.name === 'hsmAlert') {
        node.alert = true;
      } else if (event.name === 'hsmStatus') {
        node.currentHsm = event.value;
      } else {
        node.updateStatus('red', `Unknown event: ${event.name}`);
        return;
      }
      node.log(`HSM: ${node.currentHsm}`);

      if (node.sendEvent) {
        const msg = {
          payload: {
            name: event.name,
            value: event.value,
            displayName: event.displayName,
            descriptionText: event.descriptionText,
          },
          topic: 'hubitat-hsm',
        };
        node.send(msg);
      }
      const color = this.alert ? 'red' : 'blue';
      const status = this.alert ? `${node.currentHsm} - INTRUSION` : node.currentHsm;
      node.updateStatus(color, status);
    };
    this.hubitat.hubitatEvent.on('hsm', eventCallback);

    const systemStartCallback = async () => {
      const previousHsm = node.currentHsm;
      try {
        await initializeHsm();
      } catch (err) {
        return;
      }
      if (node.currentHsm !== previousHsm) {
        node.log(`Fix desynchronization: "${previousHsm}" --> "${node.currentHsm}"`);
        const event = {
          name: 'hsmStatus',
          value: node.currentHsm,
          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);

    initializeHsm().catch(() => {});

    node.on('input', async (msg, send, done) => {
      node.debug('Input received');
      if (node.currentHsm === undefined) {
        try {
          await initializeHsm();
        } catch (err) {
          return;
        }
      }

      const output = {
        ...msg,
        payload: { name: 'hsmStatus', value: node.currentHsm },
        topic: 'hubitat-hsm',
      };
      send(output);
      done();
    });

    node.on('close', () => {
      node.debug('Closed');
      this.hubitat.hubitatEvent.removeListener('hsm', 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 hsm', HubitatHsmNode);
};
